scieee AI-readable full text Open interactive document viewer

Análisis de entrenamiento en deep learning para gestión de calidad en fabricación automática

Trigueros Vega, Andrés

Abstract

Grado en Ingeniería Informática

Full text

Universidad de Valladolid Trabajo de Fin de Grado Análisis de entrenamiento en deep learning para gestión de calidad en fabricación automática Autor: Andrés Trigueros Vega Tutor: Benjamín Sahelices Fernández II AGRADECIMIENTOS Agradecimientos Este proyecto no se habría llevado a cabo de no ser por todas esas personas que han estado a mi lado durante el transcurso de la carrera. En especial: A los compañeros y amigos, los que ya tenía y los que he ido conociendo, por su compañía y apoyo en los peores momentos y su indispensable presencia en los mejores momentos. A los profesores, en especial a mi tutor Benjamín por darme los conocimientos y guiarme durante el desarrollo de este proyecto. Y por supuesto, a las personas más importantes de mi vida: mis padres y mis hermanos, que me han dedicado todo su tiempo, todo su esfuerzo y todos sus recursos con tal de educarme y formarme lo mejor posible para afrontar la vida. III AGRADECIMIENTOS IV RESUMEN Resumen El objetivo de este Trabajo de Fin de Grado es desarrollar redes neuronales que sean capaces de distinguir imágenes de soldaduras buenas (sin defectos) de imágenes de soldaduras malas (con defectos). Para entrenar las redes ha sido necesario realizar programas que simulen defectos, para lo cual se ha utilizado Python 3.9.5. Para la creación de las redes, se han utilizado tanto anaconda, que es una distribución utilizada en ciencia de datos y machine learning, como colab, que es una herramienta de Google que da acceso gratuito a GPUs. Además, se ha utilizado la librería de python fast.ai, la cual está especializada en deep learning y es la librería que más rápido ha crecido desde su creación en 2017. Por último, se realizará un estudio en el que se identificará la mejor manera de entrenar una red que no es capaz de clasificar correctamente una imagen concreta, en cuanto a tiempo y resultados. Para la realización del proyecto, se ha seguido el marco de trabajo para el desarrollo ágil SCRUM. V RESUMEN VI ÍNDICE GENERAL Índice general Agradecimientos III Resumen V Índice de figuras IX 1. Introducción y objetivos 1 2. Planificación 3 2.1. Seguimiento del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2. DiagramadeGantt............................ 9 2.3. Presupuesto económico . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.3.1. Recursos humanos . . . . . . . . . . . . . . . . . . . . . . . . 11 2.3.2. Recursos para el desarrollo . . . . . . . . . . . . . . . . . . . . 11 2.4. Análisisderiesgos............................. 12 3. Introducción a las redes neuronales 15 3.1. Perceptrón................................. 15 3.2. Neuronasigmoide............................. 18 3.3. Arquitectura de las redes neuronales . . . . . . . . . . . . . . . . . . 20 3.4. Ejemplo: Red simple para clasificar dígitos manuscritos . . . . . . . . 22 3.5. Aprendizaje con el gradiente descendiente . . . . . . . . . . . . . . . 23 3.6. Código que clasifica dígitos . . . . . . . . . . . . . . . . . . . . . . . . 28 3.7. Un acercamiento al deep learning . . . . . . . . . . . . . . . . . . . . 37 3.8. Mejoras .................................. 38 3.8.1. Función de coste de entropía cruzada . . . . . . . . . . . . . . 38 3.8.2. Sobreajuste y regularización . . . . . . . . . . . . . . . . . . . 40 3.8.3. Inicialización de los pesos . . . . . . . . . . . . . . . . . . . . 42 3.8.4. Cómo elegir los hiperparámetros . . . . . . . . . . . . . . . . . 44 3.9. Un acercamiento a las redes neuronales profundas . . . . . . . . . . . 48 VII ÍNDICE GENERAL 3.10. Redes neuronales convolucionales . . . . . . . . . . . . . . . . . . . . 50 4. Contexto tecnológico: pytorch y fastai 53 4.1. Introducción................................ 53 4.2. Una primera aproximación . . . . . . . . . . . . . . . . . . . . . . . . 55 4.3. Algunas funcionalidades útiles . . . . . . . . . . . . . . . . . . . . . . 59 5. Análisis del clasificador 63 5.1. Identificación y descripción del problema . . . . . . . . . . . . . . . . 63 5.2. Dataset .................................. 64 5.3. Transformaciones............................. 68 5.4. Diseñodelmodelo............................. 73 5.5. Experimentación ............................. 76 5.6. Conclusiones................................ 80 6. Evaluación del aprendizaje 81 6.1. Descripción del problema . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.2. Descripción del dataset . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.3. Diseño de los experimentos . . . . . . . . . . . . . . . . . . . . . . . . 82 6.4. Experimentación. Análisis de aprendizaje sobre soldaduras sencillas . 84 6.4.1. Experimento1 .......................... 84 6.4.2. Experimento2 .......................... 91 6.5. Experimentación. Análisis de aprendizaje sobre soldaduras complejas 98 6.5.1. Experimento1 .......................... 98 6.5.2. Experimento2 ..........................105 6.6. Conclusiones................................112 7. Conclusiones 113 Bibliografía 115 VIII ÍNDICE DE FIGURAS Índice de figuras 2.1. Sprint1 .................................. 3 2.2. Sprint2 .................................. 4 2.3. Sprint3 .................................. 4 2.4. Sprint4 .................................. 4 2.5. Sprint5 .................................. 5 2.6. Sprint6 .................................. 5 2.7. Sprint7 .................................. 5 2.8. Sprint8 .................................. 6 2.9. Sprint9 .................................. 6 2.10.Sprint10.................................. 6 2.11.Sprint11.................................. 7 2.12.Sprint12.................................. 7 2.13.Sprint13.................................. 7 2.14.Sprint14.................................. 8 2.15.Sprint15.................................. 8 2.16.Sprint16.................................. 8 2.17.Sprint17.................................. 9 2.18.Sprint18.................................. 9 2.19.DiagramadeGantt............................ 10 2.20. Presupuesto para los recursos humanos del proyecto . . . . . . . . . . 11 2.21. Presupuesto para los recursos para el desarrollo . . . . . . . . . . . . 11 2.22. Riesgo 1: Pérdida de datos o de trabajo . . . . . . . . . . . . . . . . . 12 2.23. Riesgo 2: Enfermedad . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.24. Riesgo 3: Fallo en las máquinas . . . . . . . . . . . . . . . . . . . . . 13 2.25. Riesgo 4: Planificación irreal . . . . . . . . . . . . . . . . . . . . . . . 13 3.1. Esquema básico de un perceptrón . . . . . . . . . . . . . . . . . . . . 16 3.2. Fórmula básica salida perceptrón . . . . . . . . . . . . . . . . . . . . 16 3.3. Esquema red neuronal simple . . . . . . . . . . . . . . . . . . . . . . 17 3.4. Fórmula resumida salida perceptrón . . . . . . . . . . . . . . . . . . . 17 IX PLANIFICACIÓN Capítulo 2 Planificación 2.1. Seguimiento del proyecto Durante la realización de este proyecto se ha utilizado la metodología SCRUM, que es un proceso en el que se aplican de manera regular un conjunto de buenas prácticas para trabajar y obtener el mejor resultado posible de un proyecto. Consiste en realizar entregas parciales y regulares del producto final, priorizadas por el beneficio que aportan al receptor del proyecto, o en este caso, al tutor del proyecto.[pro] La planificación ha variado ligeramente de lo que se pensaba inicialmente, pero contábamos con tiempo para resolver estos contratiempos. Se ha dividido el tiempo en 18 “sprints”. En cada uno de ellos se llevan a cabo unas cuantas tareas, en las que se estima el tiempo de realización de la tarea y se escribe el tiempo real que ha supuesto realizar dicha tarea. Sprint 1 (22/02/2021 - 01/03/2021) Figura 2.1: Sprint 1 3 PLANIFICACIÓN Durante este sprint dejo listo todo el material que necesito para empezar el trabajo. Evidentemente no hay ninguna tarea que no haya terminado porque todas son muy cortas. Sprint 2 (01/03/2021 - 08/03/2021) Figura 2.2: Sprint 2 Durante este sprint he de hacer una lectura inicial para entender bien como funcionan las redes neuronales y el deep learning. Aunque ya tenía algunos conocimientos de como funcionaba la inteligencia artificial, me faltaban conocimientos para hacer un TFG sobre ello. Sprint 3 (08/03/2021 - 15/03/2021) Figura 2.3: Sprint 3 Durante este sprint acabo la lectura del libro y expreso en el primer apartado un resumen de lo que he aprendido. Sprint 4 (15/03/2021-22/03/2021) Figura 2.4: Sprint 4 Durante este sprint tan solo finalizo la introducción a las redes neuronales. 4 PLANIFICACIÓN Sprint 5 (22/03/2021-29/03/2021) Figura 2.5: Sprint 5 Durante este sprint empiezo a preparar el dataset que utilizaré para llevar a cabo los experimentos del estudio. Sprint 6 (29/03/2021-05/04/2021) Figura 2.6: Sprint 6 Durante este sprint sigo programando los defectos de todos los tipos de soldaduras. Sprint 7 (05/04/2021-12/04/2021) Figura 2.7: Sprint 7 Durante este sprint termino de programar los defectos de todos los tipos de soldaduras. 5 PLANIFICACIÓN Sprint 8 (12/04/2021-19/04/2021) Figura 2.8: Sprint 8 Durante este sprint ejecuto las primeras redes neuronales y realizo las primeras pruebas. Como son muchas redes neuronales y el equipo con el que cuento no es el óptimo, tardo bastante más de lo que esperaba. Me doy cuenta del desbalanceo de imágenes buenas y malas. Sprint 9 (19/04/2021-26/04/2021) Figura 2.9: Sprint 9 Durante este sprint hago augmentation de las soldaduras buenas para balancear el número de imágenes buenas y malas en los datasets y vuelvo a realizar las pruebas. Me doy cuenta de que hay que limpiar los datasets de imágenes que no están bien clasificadas. Sprint 10 (26/04/2021-03/05/2021) Figura 2.10: Sprint 10 Durante este sprint limpio los datasets de imágenes que estaban mal clasificadas y vuelvo a ejecutar las redes neuronales. Esta vez consigo tasas de error aceptables. 6 PLANIFICACIÓN Sprint 11 (03/05/2021-10/05/2021) Figura 2.11: Sprint 11 Durante este sprint escribo el análisis del clasificador, donde explico lo que he estado haciendo las últimas semanas. Comienzo la segunda lectura, el github de fastai fastbook. Sprint 12 (10/05/2021-17/05/2021) Figura 2.12: Sprint 12 Durante este sprint sigo estudiando fastai. Sprint 13 (17/05/2021-24/05/2021) Figura 2.13: Sprint 13 Durante este sprint termino de estudiar fastai. 7 PLANIFICACIÓN Sprint 14 (24/05/2021-31/05/2021) Figura 2.14: Sprint 14 Durante este sprint realizo la escritura del contexto tecnológico. Sprint 15 (31/05/2021-07/06/2021) Figura 2.15: Sprint 15 Durante este sprint realizo los experimentos de evaluación del aprendizaje. Como no dispongo del mismo material del que contaba anteriormente, tardo más de lo que esperaba. Sprint 16 (07/06/2021-14/06/2021) Figura 2.16: Sprint 16 Durante este sprint finalizo los experimentos de la evaluación del aprendizaje y realizo la escritura de esta sección. 8 PLANIFICACIÓN Sprint 17 (14/06/2021-21/06/2021) Figura 2.17: Sprint 17 Durante este sprint realizo la escritura de la planificación (la cual estaba escribiendo en sucio en un programa diferente), y todas las subsecciones, y escribo la introducción y los objetivos. Sprint 18 (21/06/2021-28/06/2021) Figura 2.18: Sprint 18 Durante este sprint realizo una lectura final del proyecto y corrijo errores y erratas que encuentro. 2.2. Diagrama de Gantt Los diagramas de Gantt permiten comunicar visualmente el cronograma del proyecto de forma simple y comprensible.[ven] El diagrama de Gantt del proyecto sería el siguiente: 9 Figura 2.19: Diagrama de Gantt PLANIFICACIÓN 2.3. Presupuesto económico En esta sección se recoge el presupuesto económico del proyecto, de acuerdo a la planificación previamente mencionada. 2.3.1. Recursos humanos Figura 2.20: Presupuesto para los recursos humanos del proyecto 2.3.2. Recursos para el desarrollo Figura 2.21: Presupuesto para los recursos para el desarrollo 11 PLANIFICACIÓN 2.4. Análisis de riesgos Se van a listar los principales riesgos a los que está sometido el proyecto, junto con una pequeña descripción, la probabilidad de que suceda, el impacto que tendría en el proyecto, una lista con acciones de mitigación y una lista de acciones de contingencia. Figura 2.22: Riesgo 1: Pérdida de datos o de trabajo Figura 2.23: Riesgo 2: Enfermedad 12 INTRODUCCIÓN A LAS REDES NEURONALES De esta manera, la forma de la función pasa de tener esta forma: Figura 3.7: Forma función perceptrón A tener la siguiente forma: Figura 3.8: Forma función neurona sigmoide Este suavizado de la función es el que produce pequeños cambios en la salida cuando se realizan pequeños cambios en los bias y los pesos. 19 INTRODUCCIÓN A LAS REDES NEURONALES De hecho, gracias al cálculo, podemos aproximar con relativa precisión estos cambios en la salida gracias a la siguiente fórmula: Figura 3.9: Formula básica salida neurona sigmoide Al utilizar las neuronas sigmoides, como hemos explicado anteriormente, no solo el input pasa de poder tener valores únicamente binarios (0 o 1) a tener valores intermedios, como el 0.716. También el output podrá tomar estos valores intermedios. Por esta razón, es posible que la salida de una red en la que se identifican números manuscritos (ejemplo que utilizaremos más adelante), dé como resultado que una imagen contenga un 4 con una probabilidad de 0.98, un 9 con una probabilidad de un 0.01, y así con todos los dígitos. Es más difícil (aunque más práctico y preciso) interpretar esta salida, que la salida de un perceptrón, en el que sale un dígito con una probabilidad de 1, y el resto con una probabilidad de 0. 3.3. Arquitectura de las redes neuronales Como he mencionado previamente, en una red como la que se muestra a continuación, a las neuronas que forman la primera capa (o capa de entrada), se las denomina neuronas de entrada y a la neurona o las neuronas que forman la última capa (o capa de salida), se las llaman neuronas de salida. Todas las demás neuronas se encuentran en las capas ocultas (que es simplemente, una manera de dar nombre a las capas que no son ni de entrada ni de salida). Por razones históricas, a estas redes de muchas capas se las llama MLPs (que son las siglas en inglés de “multilayer perceptrons”, que significa perceptrones de muchas capas), aunque esto puede llegar a ser confuso, ya que no están formadas por perceptrones, sino por neuronas sigmoides. El diseño de las capas de entrada y salida suele ser siempre bastante parecido. El número de neuronas que tiene la capa de entrada suele ser igual al número de píxeles que tienen las imágenes que estamos tratando de clasificar (por ejemplo, si es de 64 píxeles de alto y 64 píxeles de ancho, la red tendrá una capa de entrada de 4096 neuronas sigmoides, y la de salida, dependerá de lo que se busque con la red. Si simplemente se quiere diferenciar si en una imagen hay un perro o no, solamente tendrá una neurona sigmoide, que tendrá un output en el que si la salida es mayor 20 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.10: Esquema partes de una red neuronal que 0.5, el resultado es que la imagen sí contendrá un perro, y menor que 0.5, que significará que la imagen no contiene un perro. Al igual que estas capas suelen ser bastante sencillas, las capas ocultas suelen ser más misteriosas. De hecho, no es posible resumir el proceso de diseño de las capas ocultas con unas reglas sencillas. De hecho, los investigadores de redes neuronales, han desarrollado numerosos diseños heurísticos para las capas intermedias, que ayudan a la gente a entender el comportamiento que quieren que tengan sus redes. De hecho, hasta ahora todas las redes utilizaban la salida de la capa anterior como entrada de la capa, y la salida de la capa, como entrada de la capa siguiente. A este tipo de redes se las llama redes neuronales feedforward, que significa que no tienen bucles en el interior de la red. La información siempre va hacia adelante (forward, en inglés), y nunca hacia atrás. Sin embargo, hay modelos de redes neuronales en los que los bucles, sí que son posibles. A estos modelos, se les llama redes neuronales recurrentes, y en estas redes, las neuronas se activan y desactivan temporalmente en forma de cascada. De esta manera, los bucles no causan ningún problema, ya que las salidas solo afectan a las entradas un tiempo después, no instantáneamente. De momento, las redes neuronales recurrentes han sido menos influyentes que las feedforward, ya que de momento, son menos potentes, aunque siguen siendo muy interesantes, y mucho más parecidas a como funcionan las neuronas de nuestro cerebro. Probablemente, estas redes acabarán resolviendo problemas que las redes feedforward no sean capaces de resolver, o tarden demasiado tiempo, o simplemente con más facilidad que estas, pero como de momento se utilizan menos, y están menos desarrolladas, utilizaré solo las feedforward. 21 INTRODUCCIÓN A LAS REDES NEURONALES 3.4. Ejemplo: Red simple para clasificar dígitos manuscritos Para realizar una primera aproximación a este ejemplo, que ampliaremos y mejoraremos más adelante, vamos a hacer nuestra primera red neuronal que clasifique dígitos manuscritos del 0 al 10, es decir, que la red obtenga como imagen de input lo siguiente: Figura 3.11: Ejemplo dígito manuscrito E identifique que se trata de un “5”. Para que la red sea capaz de clasificar correctamente este tipo de imágenes, crearemos una red convolucional que estará formada por 3 capas: 1. La capa de entrada (input layer), estará formada por 764 neuronas sigmoides (ya que las imágenes que vamos a utilizar tienen 28 píxeles de ancho y 28 píxeles de alto, y eso crea un cuadrado de 764 píxeles), y como cada píxel almacena un número, que representa la intensidad del píxel en blanco y negro (0.0 representando el blanco, 1.0 representando el negro y los valores intermedios representando la escala de grises). No tendremos las 3 capas (rojo, verde y azul) que tienen todos los píxeles usualmente en las imágenes, de manera que nos ahorramos neuronas gracias a esto. 2. En las capas ocultas (hidden layers), elegiremos nosotros de manera arbitraria el número de neuronas sigmoides que queremos que tengan. En este caso, he decidido que haya una sola capa que tenga quince neuronas, pero no por ninguna razón en particular. 3. Por último, la capa de salida (output layer), tendrá el mismo número de neuronas como posibles resultados tenga la red. En este caso, tendrá diez neuronas sigmoides, representando los diez valores que pueden tomar los dígitos (del 0 al 9). 22 INTRODUCCIÓN A LAS REDES NEURONALES De esta manera, la red que generaremos tendrá 764 - 15 - 10 neuronas sigmoides, y más o menos, tendrá la siguiente forma: Figura 3.12: Esquema ejemplo red neuronal dígitos manuscritos 3.5. Aprendizaje con el gradiente descendiente Lo primero que necesitaremos para hacer que la red “aprenda”, es tener un dataset que sirva para entrenar la red, con las imágenes bien clasificadas, y un dataset (independiente al anterior), que sirva para probar la red, con la que obtendremos su tasa de error. Para hacer que esta red “aprenda”, utilizaremos una función llamada “función cuadrática de coste”: Donde “C” es la función cuadrática de coste, “w” es la colección de todos los pesos de la red, “b”, la colección de todos los bias, “n” es el número de inputs de entrenamiento, 23 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.13: Función cuadrática de coste “a” es el vector de salida de la red cuando “x” es el input, e “y” es la salida deseada (y real) para el input “x”. Para el ejemplo anterior utilizado de los dígitos manuscritos, las imágenes tienen 28x28 píxeles, por lo que cada “x” es un vector con 784 valores, cada uno de ellos representando el valor de la escala de grises de cada píxel de la imagen. El resultado deseado, como se ha expresado antes, viene dado por “y”, que para este caso, se trata de un vector que siempre contiene 10 valores, de tal manera que si el resultado deseado para el un input “x” es 6, entonces y(x) = (0,0,0,0,0,0,1,0,0,0)T. Como es evidente, el resultado de esta función jamás puede ser negativo, y cuanto más se parezcan los resultados de salida de la red a los deseados, “C” será menor, y por lo tanto, si “C” es grande, los resultados de salida de la red distan de los resultados deseados. De esta manera, se ve que el objetivo es minimizar la función “C”, es decir, que buscamos un set de pesos y bias que hagan que la función tome el menor valor posible. Esto se hará usando un algoritmo llamado gradiente descendiente. Para explicar esto, imaginemos primero simplemente una función con muchas variables, por ejemplo C(v), que puede ser cualquier función de valores reales donde v=v1, v2... y queremos minimizar dicha función. 24 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.14: Gráfico de ejemplo funcionamiento gradiente descendiente 1 Por supuesto, en este ejemplo, es muy sencillo de ver, pero utilizaremos este ejemplo para explicar el gradiente descendiente. Una manera de hacer esto es utilizando cálculo, calculando las derivadas y después buscar dónde C es un extremo. Este método es muy efectivo con pocas variables, pero en cuanto hay más de 5 o 6 variables este método tarda demasiado, y no digamos en las redes neuronales más grandes que se utilizan hoy en día, con billones de pesos y bias. Esta manera es inadmisible. Por suerte para nosotros, existe otra manera de hallar los mínimos, y una analogía con la que es muy sencillo de entender. Imaginemos por un momento que la función es un valle. Imagina también que ponemos una bola en algún punto de la función. Si imaginamos que existe la gravedad, evidentemente esta bola acabará en algún mínimo en algún momento. Por lo tanto, esto es lo que vamos a utilizar. Elegimos un punto aleatorio para poner una pelota (imaginaria), y simulamos el movimiento que tomaría la pelota rodando hasta la parte más baja del valle (esto lo conseguimos calculando la primera o segunda derivada de C). El cálculo nos ayuda a calcular ∆Cconociendo ∆v1y∆v2: 25 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.15: Fórmula gradiente descendiente 1 Tenemos de encontrar las ∆v1y∆v2que hagan ∆Cnegativa (para que vaya hacia abajo). Para esto, definimos el vector ∆v≡(∆v1,∆v2)Ty el gradiente como: Figura 3.16: Fórmula gradiente descendiente 2 Y de esta manera, ∆Cpuede escribirse como ∆C≈ ∇C·∆v. Gracias a esto, imaginando un ηpequeño, podemos calcular el ∆v=−η∇C. Y así podemos ir calculando la v mediante: Figura 3.17: Fórmula gradiente descendiente 3 Lo que creará un movimiento en la pelota, con lo que cambiará su posición. Después de esto habrá que volver a calcular su v y de esta manera bajará siempre, hasta que llegue al mínimo. Y así podemos ir calculando la v mediante: Y esto, ¿Cómo se aplica al aprendizaje de una red neuronal? La idea es usar el gradiente descendiente para encontrar los pesos y los bias que minimicen el coste Cde la función cuadrática de coste. Si reemplazamos en la anterior fórmula las variables de vjpor las variables wkybl, obtenemos las siguientes fórmulas: De esta manera se consiguen los pesos y los bias que minimizan al máximo el coste C de la función cuadrática de coste, y con ello, aumentaremos el número de resultados bien clasificados. 26 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.18: Gráfico de ejemplo funcionamiento gradiente descendiente 2 Figura 3.19: Fórmula gradiente descendiente 4 Sin embargo, esto va muy lento, ya que para computar ∇C, tenemos que calcular todos los ∇Cxy después calcular su media. Para hacer esto más rápido, utilizamos el gradiente de descenso estocástico. Lo que se hace es calcular algunos ∇Cxde manera aleatoria, y así obtenemos un ∇Cbastante bueno. Para esto se cogen de manera aleatoria m inputs, a los que llamaremos mini-lotes y calcularemos su media, que debería ser parecida a la obtenida si utilizaremos todos los ∇Cx. Se van cogiendo subconjuntos aleatorios (mini lotes) y se van entrenando los pesos y los bias: Cuando se han utilizado todos los elementos del conjunto de entrenamiento, se acaba 27 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.20: Fórmula gradiente descendiente 5 la epoch, y se empieza la siguiente época de entrenamiento. Esto del gradiente y la razón por la que se coge un mini-lote es porque solo queremos saber la dirección aproximada a la que tiene que “rodar la pelota”. 3.6. Código que clasifica dígitos Utilizaremos un pequeño ejemplo para dar a entender cómo funciona un red neuronal que clasifica dígitos manuscritos. Lo escribiremos en Python (2.7) ya que se puede programar una red relativamente sencilla (tan solo 74 líneas de código), con facilidad. Para entrenarla, vamos a utilizar un dataset llamado MNIST, que contiene 50000 imágenes para el conjunto de entrenamiento (con lo que se ajustan los pesos y los bias), 10000 para el conjunto de validación (con los que se va comprobando que los pesos y los bias se van ajustando correctamente) y 10000 para el conjunto de prueba (con los que obtendremos una tasa de error que nos servirá para comprobar la bondad de nuestra red neuronal). Vamos a ir explicando poco a poco como funciona el código: Este es el código que se utilizará para inicializar el objeto “Network”. El array “sizes” contiene el número de neuronas de cada capa, de tal manera que si se llama a la clase Network de la siguiente manera: “net = Network([2, 3, 1])”, significará que la primera capa tendrá 2 neuronas, la segunda capa, 3 y la tercera y última, 1. Los bias y los pesos de todas las capas sin contar la primera, se inicializan de manera aleatoria utilizando “np.random.randn”, que es una función que genera un número aleatorio con media 0 y desviación estándar 1, con una distribución Gausiana. De esta manera, tenemos datos con los que empezar a trabajar, aunque hay manera mejores de hacerlo. 28 INTRODUCCIÓN A LAS REDES NEURONALES 120 def evaluate(self ,test_data) : 121 """ Return the number of test inputs for which the neural 122 network outputs the correct result . Note that the neural 123 network ’s output is assumed to be the index of whichever 124 neuron in the final layer has the highest activation . """ 125 test_results = [ ( np .argmax(self .feedforward(x) ) , y) 126 for (x,y)in test_data ] 127 return sum (int (x== y)for (x,y)in test_results) 128 129 def cost_derivative(self ,output_activations ,y) : 130 """ Return the vector of partial derivatives \ partial C_x / 131 \ partial a for the output activati ons . """ 132 return (output_activations -y) 133 134 # ### Misce llaneous func tions 135 def sigmoid(z) : 136 """ The sigmoid funct ion . """ 137 return 1.0/(1.0+np .exp (-z) ) 138 139 def sigmoid_prime(z) : 140 """ Der ivat ive of the sigm oid f unction . """ 141 return sigmoid(z)∗(1 -sigmoid(z) )   Listing 3.1: Código completo Para ejecutar el programa, se puede utilizar el programa de ayuda mnist_loader: Figura 3.27: Código parte 6 En este ejemplo, se van a utilizar 30 neuronas en la capa oculta, por lo que se llamará a la red de la siguiente manera: Figura 3.28: Código parte 7 Y el descenso de gradiente estocástico, lo seleccionamos con 30 épocas (epoch), los tamaños de los mini-lotes de 10 y una tasa de aprendizaje ( η) de 3.0: Figura 3.29: Código parte 8 El resultado del código tiene el siguiente aspecto: 35 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.30: Resultado código Como puede observarse, muestra, en función de las épocas, el número de imágenes bien clasificadas de las totales. En la primera época, ya clasifica correctamente 9129 de las 10000, y en la última, 9534, lo que quiere decir, que con esta red, y con estos datos, la red clasifica correctamente en torno a un 95 % de las imágenes. Si volvemos a ejecutar la red utilizando 100 neuronas en la capa intermedia, evidentemente, tardará más tiempo en ejecutarse, pero conseguirá eventualmente un resultado mejor (más de un 96 %), aunque puede que haya ejecuciones que empeoren el porcentaje, debido a la varianza. Los hiperparámetros de la red (el número de épocas de entrenamiento, el tamaño de los mini-lotes y la tasa de aprendizaje ( η)) es importante que sean todos razonables. Por ejemplo, si ponemos una tasa de aprendizaje de 0.001, conseguiremos los siguientes resultados: Figura 3.31: Resultado código 2 Como puede observarse, se obtiene un resultado notablemente peor, aunque va mejorando lentamente a lo largo de las “epoch”. Este no es el caso de este otro ejemplo, en el que se ejecuta el programa con 30 neuronas en la capa oculta y una tasa de aprendizaje ( η) de 100.0, donde obtengo los siguientes resultados: 36 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.32: Resultado código 3 Y viendo estos resultados, y sin saber que con una tasa de aprendizaje de 3.0 salen buenos resultados, no sabemos qué le pasa a la red. No sabemos si hemos inicializado los pesos y bias de tal manera que hace difícil a la red aprender, o no tenemos suficientes datos en el dataset de entrenamiento, o no tenemos suficientes épocas, o la tasa de aprendizaje es demasiado baja, o demasiado alta... Por estas razones, debuguear una red neuronal, es difícil. 3.7. Un acercamiento al deep learning Es cierto que el interior de una red neuronal es bastante misteriosa ahora mismo. Para que nosotros podamos entender cómo funciona, vamos a poner un ejemplo en el que se entiende bastante bien cómo funciona por dentro. Imagina que queremos crear una red neuronal que descubra si en una imagen hay caras humanas o no. Para esto, una heurística que podemos utilizar para resolver el problema es separarlo en subproblemas, como si hay un ojo en la parte superior izquierda, un ojo en la parte superior derecha, una nariz en el medio, una boca en medio abajo, pelo en la parte de arriba...Si se dan esos casos, probablemente estemos ante una cara. Por supuesto, esta heurística tiene defectos. Por ejemplo, si la persona es calva, o por el ángulo no se ve un ojo... pero esto es solo un ejemplo para que podamos entender cómo funciona, así que obviaremos estos defectos. A su vez, el ojo se puede subdividir en pestañas, ceja, iris, pupila... y así sucesivamente hasta que se subdividan en elementos cada vez más simples hasta llegar a los píxeles, que es nuestra entrada a la red. 37 INTRODUCCIÓN A LAS REDES NEURONALES De esta manera, una pregunta que parece muy difícil de responder, como si en una imagen hay una cara humana o no, se puede subdividir en preguntas cada vez más sencillas, hasta llegar a los píxeles, con lo que acaba siendo evidente. 3.8. Mejoras Como hemos visto, en el mejor resultado que hemos obtenido, la solución con mejor tasa de acierto era de en torno al 95 %. ¿Esto se puede mejorar? Por suerte, la respuesta es sí, y aquí enunciamos algunas de las maneras que se han encontrado para mejorar la velocidad o el porcentaje de acierto de la red. 3.8.1. Función de coste de entropía cruzada Los seres humanos, aprendemos rápido de nuestros errores cuanto más lejos están del acierto. Sin embargo, las redes neuronales que estamos estudiando no funcionan así. Imagina una neurona sigmoide con un solo input, de la que queremos que, sea cual sea el input, el output sea 0. Si escribimos los pesos y bias manualmente, es muy fácil de hacer. Sin embargo, si inicializamos estos valores de manera aleatoria y ponemos a la red a trabajar como si fuera una red de una sola capa y una sola neurona, no es tan evidente. Si inicializamos el valor del peso del input a 0.6, y el valor del bias a 0.9 (por ejemplo), el output inicial será 0.82 (esto es fácil de calcular utilizando la fórmula [3.6]. Pues bien, utilizando la función de coste [3.13] y una tasa de aprendizaje η= 0.15, tarda 300 épocas en llegar a un output de 0.09. Sin embargo, si inicializamos el peso a 2.0 y el bias a 2.0, el output inicial es de 0.98, y en 300 épocas, se baja a 0.2. Esto puede parecer “no tan malo” a primera vista, pero si nos fijamos en la forma que se crea en la función que relaciona el output con el número de épocas, nos damos cuenta de algo muy importante. Por la forma que tienen, se ve que cuanto más lejos están los pesos y los bias de los “ideales”, más épocas le cuesta a la red obtener buenos resultados. Esto se puede ver fácilmente en estas dos funciones, con los pesos y bias mencionados previamente, y la misma tasa de aprendizaje ( η= 0.15 ): 38 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.33: Relación output - épocas (peso 0.6, bias 0.9) Figura 3.34: Relación output - épocas (peso 2.0, bias 2.0) Para mejorar esto, se empezó a utilizar un método para calcular el coste que evitara esto. Voy a omitir la demostración matemática, porque no es el objetivo del trabajo, pero el que quiera profundizar, dejaré en la bibliografía lugares donde esto se explica de una forma mucho más detallada. La función que se utiliza, pasa de ser [3.13] a ser la siguiente: Figura 3.35: Relación output - épocas (peso 0.6, bias 0.9) En esta función, las variables son las mismas que en la función anterior, pero utilizando este método, se evita esa ralentización que se produce al distar mucho los pesos y bias originales de los finales. Los resultados de estos dos mismos ejemplos utilizando este método, son los siguientes: 39 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.36: Relación output - épocas (peso 0.6, bias 0.9) Figura 3.37: Relación output - épocas (peso 2.0, bias 2.0) Como curiosidad, para estos dos últimos ejemplos, la tasa de aprendizaje (η), es de 0.005, aunque esto no es una reducción, ya que ambas magnitudes no son comparables. Es como comparar peras con olmos. En el fondo, da igual cómo de bueno acabe siendo o la rapidez de mejora, lo importante es la diferencia entre las formas de las gráficas, y lo que ello conlleva. 3.8.2. Sobreajuste y regularización El sobreajuste es el efecto de sobreentrenar un algoritmo de aprendizaje. El algoritmo de aprendizaje debe alcanzar un estado en el que será capaz de predecir el resultado utilizando la generalización. Esto se entiende muy fácilmente con la siguiente imagen: 40 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.38: Ejemplo sobreajuste Como puede observarse, la línea negra probablemente tendrá menos errores en datos futuros que la verde, pese a que la verde diferencie perfectamente los datos con los que contamos.[Wike] Este es uno de los mayores problemas de las redes neuronales, y necesitamos una manera de detectar cuando se está produciendo un sobreajuste para no sobreentrenar la red, y desarrollar técnicas que reduzcan los efectos del sobreentrenamiento. Una de las maneras más evidentes es llevar un seguimiento de la tasa de acierto mientras nuestra red se va entrenando, y utilizar el test de prueba, es decir, que si vemos que la tasa de error no está mejorando, debemos dejar de entrenar. Otra manera es utilizando el dataset de validación. Hasta ahora, solo hemos hecho incapié en los dataset de entrenamiento, con los que se entrenaba la red y se configuraban los pesos y bias, y el dataset de prueba, con el que se obtenía la bondad de la red con la tasa de error. Si hacemos un poco de memoria, dije que el dataset que estábamos utilizando tenía 70000 imágenes, de las cuales 50000 iban a ser utilizadas para el dataset de entrenamiento, 10000 para el dataset de prueba y 10000 para el dataset de validación, pero nunca llegué a explicar para qué valía este. Esta segunda manera, utilizando el dataset de validación, es significativamente mejor que la anterior. Para realizar esta comprobación, comprobamos la precisión del dataset de validación al final de cada época. Cuando la precisión se sature, paramos el entrenamiento en esa época. A esta técnica se la llama “early stopping”, que en inglés significa “paro rápido”. En la práctica no sabemos cuando se ha saturado, así que lo que hacemos es seguir 41 INTRODUCCIÓN A LAS REDES NEURONALES entrenando hasta que estemos seguros de que se ha saturado. Los hiperparámetros (el número de épocas, la tasa de aprendizaje, la arquitectura, el tamaño de los mini-lotes...), se seleccionan utilizando el dataset de validación, y esto es así, y no utilizando el dataset de prueba porque si se utilizara directamente el dataset de prueba, podría darse el caso que la red encaje de una manera correcta para los datos del dataset de prueba concreto, pero que no llegue a generalizar. De esta manera, tenemos una última prueba para asegurar que se ha generalizado correctamente. A este método se le suele llamar “hold out”, ya que el dataset de validación se aparta, que es lo que significa “hold out” en inglés. Hay maneras de reducir el sobreentrenamiento, ya sea con datasets más grandes, utilizando redes más pequeñas, o utilizando las técnicas de regularización. No ahondaré en estas técnicas de regularización, pero dejo en la sección de bibliografía más información por si se quiere profundizar. Para obtener datasets más grandes, se pueden conseguir más datos, lo que suele ser bastante caro, pero también existen otras maneras de conseguir más datos, como por ejemplo, realizar pequeñas rotaciones a las imágenes, por ejemplo: Figura 3.39: Ejemplo expansión de dataset barata Ya que el dígito sigue siendo reconocible, pero a nivel de píxeles, es diferente. También se pueden realizar recortes de imágenes en las que siga siendo reconocible el dígito, traslaciones... con los que conseguimos mejores resultados en nuestras redes. De hecho, en casi todos los casos y para casi todos los algoritmos, cuantos más datos se tengan para entrenar, mejor será la red (mejor tasa de acierto tendrá). 3.8.3. Inicialización de los pesos Hasta ahora, inicializábamos los pesos y los bias mediante variables aleatorias gausianas independientes, con media 0 y desviación estándar 1, sin embargo, existen maneras mejores de inicializar estas variables. 42 INTRODUCCIÓN A LAS REDES NEURONALES La razón por la que esto no es lo más óptimo es porque para ciertos inputs (solo unos y ceros, por ejemplo), se acaban generando salidas de neuronas sigmoides muy cercanas a los dos extremos, ya sea 1 o 0, y un pequeño cambio en un peso o un bias, hará un cambio minúsculo en la siguiente capa, y así sucesivamente. La red se satura y tardará muchas épocas en aprender. Este es un problema similar al que resolvimos con la función de coste de entropía cruzada, en el que veíamos que cuanto más se alejara un dato del dato óptimo para la red, más tiempo tardaba en optimizarse. Sin embargo, esta función solo nos ayudaba para la capa de salida, no para las capas ocultas. La manera que se ha encontrado de mejorar esto es utilizar una distribución gausiana aleatoria con la misma media (0), pero una desviación típica diferente (1/√nin, siendo nin el número de pesos de entrada). De esta manera, la distribución Gausiana pasa de tener la siguiente forma: Figura 3.40: Curva distribución Gausiana 1 A tener la siguiente forma: Figura 3.41: Curva distribución Gausiana 2 En el caso de los bias, no generan saturación, así que podemos seguir utilizando el 43 INTRODUCCIÓN A LAS REDES NEURONALES mismo código para generarlos. Hay quien los inicializa todos a 0, pero no genera diferencias. Como puede observarse en esta gráfica en la que se representan las tasas de acierto en función de las épocas de entrenamiento, esta manera de inicializar los pesos es notablemente mejor, pese a que al final se llegue al mismo resultado: Figura 3.42: Diferencias en tasa de acierto en función de la inicialización pesos 3.8.4. Cómo elegir los hiperparámetros Como hemos explicado previamente, los hiperparámetros son: la tasa de aprendizaje (η), el tamaño de los mini-lotes, el número de épocas, el número de neuronas ocultas, el parámetro de regularización (λ)... Imagina que estamos en la siguiente situación: estamos haciendo la red que clasifica dígitos y nos sabemos qué parámetros utilizar. Por casualidad, conseguimos buenos parámetros para el número de neuronas ocultas (30), el tamaño de los mini-lotes (10), el número de épocas (30), pero elegimos mal la tasa de aprendizaje (10), y el parámetro de regularización (1000). Con estos datos obtenemos los siguientes resultados: Como puede observarse, estos resultados no son aceptables. Hasta un bebé sin ningún conocimiento, pulsando botones al azar, puede obtener un resultado similar o mejor. 44 INTRODUCCIÓN A LAS REDES NEURONALES Figura 3.48: Campos receptivos locales red convolucional De esta manera, la pasamos de tener 28x28 neuronas en la capa de entrada a tener 24x24 neuronas en la primera capa de la capa oculta, y están relacionadas por su estructura espacial. 2. Pesos y bias compartidos: Todos los pesos y bias son los mismos para cada neurona. Es decir, que el peso de la primera neurona de la capa de entrada para la primera neurona de la primera capa de la capa oculta es el mismo que el peso de la segunda neurona de la capa de entrada para la segunda neurona de la primera capa de la capa oculta, y así sucesivamente con todos. De esta manera, todas las neuronas de la misma capa oculta buscan la misma característica, y así, aunque la figura (por ejemplo, un gato), no esté en el centro, la red se adapta. Por esta razón, a la primera capa de la capa oculta se la llama “mapa de características”. Y no tiene por qué ser siempre 1, puede haber más. 51 INTRODUCCIÓN A LAS REDES NEURONALES 3. Agrupación de capas: Este proceso se realiza a continuación de la creación del mapa de características. Se realiza esto para condensar la información y reducir el tamaño de la matriz que produce. La forma de llevar esto a cabo es seleccionar fragmentos de la matriz de 2x2 y escoger el valor más alto, o el valor medio de la matriz, dependiendo de si se realiza “max pooling” o “average pooling” respectivamente. Un ejemplo de esquema de una red convolucional sería el siguiente: Figura 3.49: Ejemplo esquema red convolucional Como puede observarse, inicialmente tenemos una imagen de 28x28 píxeles, desde la cual se obtienen 3 mapas de características con diferentes patrones, cada una de 24x24 neuronas, y a continuación se realiza un “max pooling” o un “average pooling” y acaban quedando 3 matrices de 12x12 neuronas, con la información seleccionada y comprimida. 52 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI Capítulo 4 Contexto tecnológico: pytorch y fastai 4.1. Introducción Para la realización de este estudio, se va a utilizar fast.ai (versión 2), que es la librería de deep learning que más rápido ha crecido desde su creación, en 2017, y hoy en día es usada por la mayoría de los trabajos de investigación de las principales conferencias. Además, es la librería más flexible y más expresiva de la biblioteca de deep learning. No cambia velocidad por simplicidad, sino que provee ambas. El manual del que en el que me voy a basar para explicar la librería ha sido creada por Sylvain y Jeremy, que son educadores, matemáticos, y expertos en aprendizaje automático. Ellos creen que el aprendizaje profundo tiene poder, flexibilidad y simplicidad, y que debería aplicarse en muchas disciplinas (ciencias sociales y físicas, las artes, la medicina, las finanzas, la investigación científica...). De hecho, explican que a pesar de no tener experiencia en medicina, Jeremy fundó Enlitic, una empresa que utiliza algoritmos de aprendizaje profundo para diagnosticar enfermedades y dolencias. A los pocos meses de iniciar la empresa, se anunció que su algoritmo podía identificar tumores malignos con mayor precisión que los radiólogos. De hecho, el deep learning se puede utilizar para multitud de campos diferentes. Aquí hay una lista de algunas de las miles de tareas en diferentes áreas en las que el deep learning, o los métodos que utilizan en gran medida el aprendizaje profundo, 53 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI son ahora los mejores del mundo: 1. Procesamiento del Lenguaje Natural: Responder preguntas, reconocimiento de voz, resumir documentos, clasificación de documentos, buscar artículos que mencionen un concepto... 2. Visión por computadora: interpretación de imágenes de satélites y drones , reconocimiento facial, leer señales de tráfico, localizar peatones y vehículos en vehículos autónomos... 3. Medicina: Detección de anomalías en imágenes de radiología, , contar características en diapositivas de patología, características de medición en ultrasonidos, diagnosticar la retinopatía diabética... 4. Videojuegos: Ajedrez, Go, la mayoría de los videojuegos de Atari, muchos juegos de estrategia en tiempo real... Han completado cientos de proyectos de aprendizaje automático utilizando docenas de paquetes diferentes y muchos lenguajes de programación diferentes. En fast.ai, han escrito cursos que utilizan la mayoría de los principales paquetes de aprendizaje profundo y aprendizaje automático que se utilizan en la actualidad. Después de que PyTorch saliera a la luz en 2017, pasaron más de mil horas probándolo antes de decidir que lo usarían para futuros cursos, desarrollo de software e investigación. Desde entonces, PyTorch se ha convertido en la biblioteca de aprendizaje profundo de más rápido crecimiento en el mundo y ya se utiliza para la mayoría de los trabajos de investigación en las principales conferencias. Este es generalmente un indicador adelantado de uso en la industria, porque estos son los papeles que terminan usándose comercialmente en productos y servicios. Hemos descubierto que PyTorch es la biblioteca más flexible y expresiva para el aprendizaje profundo. No intercambia velocidad por simplicidad, sino que proporciona ambas. PyTorch funciona mejor como una biblioteca básica de bajo nivel, proporcionando las operaciones básicas para una funcionalidad de nivel superior. La biblioteca fastai es la biblioteca más popular para agregar esta funcionalidad de nivel superior a PyTorch. También se adapta particularmente bien a los propósitos de este proyecto, porque es único en proporcionar una arquitectura de software profundamente estratificada (incluso hay un artículo académico revisado por pares sobre esta API estratificada). La plataforma de experimentación que vamos a utilizar se llama Colaboratory. Ya que es una herramienta popular para hacer ciencia de datos en Python, potente, flexible, fácil de usar y gratuita. 54 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI 4.2. Una primera aproximación El código de una red neuronal utilizando esta herramienta tiene el siguiente aspecto: Figura 4.1: Ejemplo código red neuronal fastai 55 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI La primera sección importa las librerías. La segunda sección inicializa la variable path para indicar la ruta de la que se van a tomar los datos. La tercera sección crea un datablock llamado “soldaduras”, que es un sistema extremadamente flexible llamado “API de datablock”. Con esta API, se puede personalizar completamente cada etapa de la creación de sus DataLoaders. En este caso, proporcionamos una tupla donde especificamos qué tipos queremos para las variables independientes y dependientes, en este caso, “ImageBlock” y “CategoryBlock” respectivamente. La variable independiente es lo que estamos usando para hacer predicciones, y la variable dependiente es nuestro objetivo. En este caso, nuestras variables independientes son imágenes y nuestras variables dependientes son las categorías (tipo de soldadura) para cada imagen. A continuación, tenemos que decirle a fastai cómo obtener una lista de esos archivos. La función get_image_files toma una ruta y devuelve una lista de todas las imágenes en esa ruta. Después, dividimos nuestros conjuntos de entrenamiento y validación al azar (en este caso, un 20% de las imágenes no serán utilizadas para el conjunto de entrenamiento y se reservarán para el conjunto de prueba). Sin embargo, nos gustaría tener la misma división de entrenamiento / validación cada vez que ejecutamos este cuadro, por lo que utilizamos la semilla aleatoria (las computadoras realmente no saben cómo crear números aleatorios, simplemente crean listas de números que parecen aleatorios ; si proporciona el mismo punto de partida para esa lista cada vez, llamado semilla, obtendrá exactamente la misma lista cada vez). En este caso utilizarmos la semilla 42. Por último, le decimos a fastai cómo crear las etiquetas en nuestro conjunto de datos. En este caso, utilizamos la función “parent_label”, que es una función proporcionada por fastai que simplemente obtiene el nombre de la carpeta en la que se encuentra un archivo. Debido a que colocamos cada una de nuestras imágenes de soldaduras en carpetas según el tipo de soldadura, esto nos dará las etiquetas que necesitamos. La cuarta sección creamos una instancia del objeto “soldaduras” que hemos creado antes. Después, este comando nos proporciona un objeto DataBlock, utilizando la ruta que habiamos asignado como variable previamente. En la quinta sección, se le indica a fastai que cree una red neuronal convolucional (CNN) y especifica qué arquitectura usar (es decir, qué tipo de modelo crear), en qué datos queremos entrenarlo y qué métrica usar. CNN es el enfoque actual de vanguardia para crear modelos de visión por compu56 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI tadora. Se le indica el datablock que se quier utilziar, en este caso, “dls”. Hay algunas arquitecturas estándar que funcionan la mayor parte del tiempo, y en este caso estamos usando una llamada ResNet. El 18 en resnet18 se refiere al número de capas en esta variante de la arquitectura (otras opciones son 34, 50, 101 y 152). Los modelos que usan arquitecturas con más capas tardan más en entrenarse y son más propensos a sobreajustarse (es decir, no puede entrenarlos durante tantas épocas antes de que la precisión en el conjunto de validación comience a empeorar), aunque, cuando se utilizan más datos, pueden ser un poco más precisos. Por último, se indica la métrica. Una métrica es una función que mide la calidad de las predicciones del modelo utilizando el conjunto de validación y se imprimirá al final de cada época. En este caso, estamos usando error_rate, que es una función proporcionada por fastai que hace exactamente lo que dice: qué porcentaje de imágenes en el conjunto de validación se clasifican incorrectamente. “cnn_learner” también tiene un parámetro preentrenado, que por defecto es Verdadero (por lo que se usa en este caso, aunque no se ha especificado), que establece los pesos en su modelo en valores que ya han sido entrenados por expertos para reconocer mil diferentes categorías en 1,3 millones de fotos (utilizando el famoso conjunto de datos ImageNet). Un modelo que tiene ponderaciones que ya se han entrenado en algún otro conjunto de datos se denomina modelo preentrenado. Casi siempre debe usarse un modelo previamente entrenado, porque significa que su modelo, incluso antes de que le haya mostrado alguno de sus datos, ya es muy capaz. En un modelo de aprendizaje profundo, muchas de estas capacidades son cosas que se necesitarán, casi independientemente de los detalles de su proyecto. Por ejemplo, partes de modelos previamente entrenados manejarán la detección de bordes, degradados y color, que son necesarios para muchas tareas. Además, se le dice a fastai cómo ajustar el modelo. Esta es la clave del aprendizaje profundo: determinar cómo ajustar los parámetros de un modelo para que resuelva el problema. Para ajustar un modelo, tenemos que proporcionar al menos una pieza de información: cuántas veces mirar cada imagen (conocido como número de épocas). El número de épocas que se seleccionen dependerá en gran medida de la cantidad de tiempo que se tenga disponible y del tiempo que se considere que se necesita en la práctica para adaptarse a su modelo. Si se selecciona un número que es demasiado pequeño, siempre se pueden entrenar más épocas más adelante. Pero, ¿por qué el método se llama “fine_tune”? Como en este caso, comenzamos con un modelo previamente entrenado y no queremos deshacernos de todas las capacidades que ya tiene, este método establece algunos parámetros, como que se use 57 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI una época para ajustar solo aquellas partes del modelo necesarias para que el nuevo cabezal aleatorio funcione correctamente con su conjunto de datos y que se utilicen el número de épocas solicitado al llamar al método para ajustar el modelo completo, actualizando los pesos de las capas posteriores (especialmente la cabeza), más rápido que las capas anteriores (que, como veremos, generalmente no requieren muchos cambios de los pesos preentrenados). De esta manera, se imprimen los resultados después de cada época, en la que se muestran el número de época, las pérdidas del conjunto de entrenamiento y validación y cualquier métrica que haya solicitado (tasa de error, en este caso). Una vez se han ejecutado todas esas instrucciones en ese orden concreto, se genera un cuadro como el siguiente: Figura 4.2: Ejemplo salida tabla con datos red neuronal fastai 58 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI En el que, como he explicado antes, se muestra el número de la época, las pérdidas del conjunto de entrenamiento y validación y la métrica (tasa de error). 4.3. Algunas funcionalidades útiles Durante la realización del proyecto, ha habido varias funcionalidades de las que disponemos cuando utilizamos fastai que han sido de vital importancia. En esta sección se van a explicar dichas funciones, como funcionan y por qué han sido útiles. La primera función que se ha utilizado ha sido la función “.predict”. Esta función tiene el siguiente aspecto: Figura 4.3: Ejemplo código fastai función “.predict()” Esta función devuelve la predicción del item que se le pase por parámetro, utilizando la red que se ha creado previamente. Esta función devuelve, además del nombre de la clase que predice la red (en este caso, “Soldadura_Buena”), un tensor en el que indica la probabilidad de cada una de las posibles clases según la red que se haya utilizado. En este caso, hay un 99,921 % de posibilidades de ser una “Soldadura_Buena”), y un 0,079 % de posibilidades de ser la clase del otro tipo. Esto es especialmente útil sobre todo para observar la predicción de una imagen concreta con la red preentrenada. Otra función que se ha utilizado bastante ha sido la función “.recorder.plot_loss()”, que tiene el siguiente aspecto: 59 CONTEXTO TECNOLÓGICO: PYTORCH Y FASTAI Figura 4.4: Ejemplo código fastai función “.recorder.plot_loss()” Este método muestra el train_loss y el valid_loss a lo largo de las épocas de entrenamiento, y sirve para mostrar cuando se está produciendo sobreajuste en la red (se produce en el momento en el que el valid_loss sube y el train_loss baja), El siguiente método que se ha utilizado ha sido el método “.plot_confusion_matrix()”: Figura 4.5: Ejemplo código fastai función “.plot_confusion_matrix()” 60 ANÁLISIS DEL CLASIFICADOR Figura 5.5: Ejemplo imagen soldadura tipo 5 Tipo 6: contiene 2642 imágenes de soldaduras buenas y 4151 imágenes de soldaduras malas. El aspecto de las soldaduras que forman este dataset es el siguiente (en el ejemplo se marca con un círculo rojo el defecto, desplazamiento total del cordón): Figura 5.6: Ejemplo imagen soldadura tipo 6 Tipo 7: contiene 4144 imágenes de soldaduras buenas y 9482 imágenes de soldaduras malas. El aspecto de las soldaduras que forman este dataset es el siguiente (en el ejemplo se marca con un círculo rojo el defecto, agujero en el cordón): Figura 5.7: Ejemplo imagen soldadura tipo 7 Tipo 8: contiene 2097 imágenes de soldaduras buenas y 3587 imágenes de soldaduras malas. El aspecto de las soldaduras que forman este dataset es el siguiente (en el ejemplo se marca con un círculo rojo el defecto, más material en la parte superior que en la inferior): 67 ANÁLISIS DEL CLASIFICADOR Figura 5.8: Ejemplo imagen soldadura tipo 8 Tipo 9: contiene 5328 imágenes de soldaduras buenas y 8882 imágenes de soldaduras malas. El aspecto de las soldaduras que forman este dataset es el siguiente (en el ejemplo se marca con un círculo rojo el defecto, bola en la zona central del cordón): Figura 5.9: Ejemplo imagen soldadura tipo 9 5.3. Transformaciones Inicialmente el dataset solo contenía imágenes de soldaduras buenas, por lo que se han tenido que realizar programas en python para simular defectos en las imágenes de las soldaduras buenas. Para la creación de estas imágenes, se ha utilizado la librería de python “opencv” para la detección de bordes y el cálculo de gradientes, lo que fue de vital importancia para obtener una máscara del cordón y poder aislar la soldadura, así como numpy, pillow y scipy, que tienen métodos que aceleran mucho las tareas que había que llevar a cabo. 68 ANÁLISIS DEL CLASIFICADOR Las principales deformaciones que se han llevado a cabo en casi todos los tipos de soldaduras fueron los siguientes: Girar derecha arriba: Consiste en deformar la parte derecha del cordón hacia arriba, simulando una caída de cordón. Figura 5.10: Ejemplo imagen defecto derecha arriba Girar derecha abajo: Consiste en deformar la parte derecha del cordón hacia abajo, simulando una caída de cordón. Figura 5.11: Ejemplo imagen defecto derecha abajo Girar izquierda arriba: Consiste en deformar la parte izquierda del cordón hacia arriba, simulando una caída de cordón. Figura 5.12: Ejemplo imagen defecto izquierda arriba Girar izquierda abajo: Consiste en deformar la parte izquierda del cordón hacia abajo, simulando una caída de cordón. 69 ANÁLISIS DEL CLASIFICADOR Figura 5.13: Ejemplo imagen defecto izquierda abajo Abombar abajo: Consiste en deformar la parte central del cordón hacia abajo, simulando una caída de cordón. Figura 5.14: Ejemplo imagen defecto abombar abajo Abombar arriba: Consiste en deformar la parte central del cordón hacia arriba, simulando una caída de cordón. Figura 5.15: Ejemplo imagen defecto abombar arriba Descompensación norte sur: Consiste en simular más cantidad de material en la zona superior que la inferior. Figura 5.16: Ejemplo imagen defecto descompensación N/S Descompensación sur norte: Consiste en simular más cantidad de material en la zona inferior que la superior. 70 ANÁLISIS DEL CLASIFICADOR Figura 5.17: Ejemplo imagen defecto descompensación S/N Bolas: Consiste en simular una acumulación de material en un punto concreto, formando una bola en algún punto del cordón. Figura 5.18: Ejemplo imagen defecto bola Corte: Consiste en simular ausencia de material en alguna zona del cordón. Figura 5.19: Ejemplo imagen defecto corte Agujero: Consiste en simular ausencia de material en algún punto del cordón. Figura 5.20: Ejemplo imagen defecto agujero Las transformaciones que he mencionado previamente se han realizado a casi todos los datasets, sin embargo ha habido algunas excepciones, como por ejemplo en el tipo 8, que la soldadura es tan pequeña que no merece la pena simular una caída de cordón solo por la parte central. 71 ANÁLISIS DEL CLASIFICADOR Además, el tipo 5 tiene otros defectos porque la forma es totalmente diferente. También tiene agujeros, bolas, cortes y caídas de cordón, pero evidentemente, al tener otra forma son ligeramente diferentes. Todas estas transformaciones que hemos mencionado son para entrenar a la red con imágenes de soldaduras malas. Cuando se entrenaron las primeras redes, se dieron algunas situaciones en las que había más de diez imágenes de soldaduras malas por cada imagen de una soldadura buena. Por esta razón, se llegó a dar el caso de que algunas redes clasificaban todas las imágenes como malas para garantizar una buena tasa de acierto. Como no era esto lo que se pretendía, se tuvo que hacer augmentation de las imágenes buenas para que el número de imágenes de soldaduras buenas y soldaduras malas de cada dataset fueran más similares. Para crear más imágenes de soldaduras buenas, se llevaron a cabo las siguientes transformaciones: Ruido gausiano: Consiste en sustituir el valor de píxeles aleatorios por 0 para simular ruido en la imagen. Además, como los píxeles son aleatorios, se puede realizar esta acción varias veces sobre la imagen y se obtienen imágenes diferentes. Figura 5.21: Ejemplo imagen ruido gausiano Ruido aleatorio: Consiste en alterar el valor de los píxeles, y aumentar o reducir su valor un valor aleatorio. De nuevo, se puede realizar esta acción varias veces sobre la misma imagen. En la imagen es posible que no se note demasiado la diferencia, pero la intensidad de los píxeles ha variado de manera aleatoria. Figura 5.22: Ejemplo imagen ruido aleatorio 72 ANÁLISIS DEL CLASIFICADOR 5.4. Diseño del modelo Para la creación del modelo, se ha utilizado una herramienta llamada “anaconda”. Anaconda es una distribución libre y abierta de los lenguajes de programación python (que es el lenguaje que utilizaremos nosotros), y R. Es muy utilizada en ciencia de datos y aprendizaje automático. Vamos a utilizarlo porque está orientado a simplificar el despliegue y la administración de los paquetes de software.[Wika] Como es evidente por el apartado 4 de este proyecto, vamos a utilizar la librería orientada al deep learning “fastai”, que nos permitirá, con unas pocas líneas de código, obtener un clasificador que es capaz de clasificar las soldaduras con un porcentaje de acierto de más de un 99 %. Como el código es tan breve, iré explicando línea por línea lo que se va haciendo. 1. Lo primero, como siempre, importamos las librerías de fastai que nos van a hacer falta. El warning no tiene ningún impacto en el código, y cuando arreglo el warning, no ejecuta el programa, así que vamos a obviarlo. Cabe destacar que es necesario haberse descargado las librerías que vamos a utilizar en el ordenador antes de ejecutarlas. Para hacer esto basta con abrir el cmd y utilizar pip para instalar fastai y fastbook. Figura 5.23: Código red neuronal 1 2. Introducimos la ruta del directorio donde están las imágenes. En este caso es simplemente el nombre de la carpeta. Dentro de esta carpeta, hay dos carpetas, con los nombres: “Soldadura_Buena” y “Soldadura_Mala”, y en cada una de ellas, se encuentran las imágenes de las soldaduras con el preprocessing ya aplicado. Evidentemente, en Soldadura_Buena, están todas las imágenes de soldaduras sin defectos, y en Soldadura_Mala, las imágenes de soldaduras con defectos. 73 ANÁLISIS DEL CLASIFICADOR Figura 5.24: Código red neuronal 2 3. A continuación, creamos el datablock (llamado “soldaduras”). Especificamos que nuestra variable independiente serán las imágenes, que es lo que vamos a utilizar para hacer nuestras predicciones, y nuestra variable dependiente serán las categorías en las que las vamos a dividir, en este caso, soldaduras buenas y malas. Decimos a fastai que queremos obtener una lista de todos los ficheros de la ruta que hemos introducido con el get_image_files. Vamos a utilizar holdout para el cálculo de la tasa de error, así que dividimos el dataset de manera aleatoria en un 20% de imágenes formando el conjunto de prueba y un 80 % formando el conjunto de entrenamiento, y la semilla que vamos a utilizar (en este caso, 42, aunque esto da absolutamente lo mismo). Por último, especificamos que la variable dependiente (y), tomará los nombres de los ficheros padre (“Soldadura_Buena” y “Soldadura_Mala”). Figura 5.25: Código red neuronal 3 4. Después, se llama a la clase “dataloaders”, que provee mini-lotes de unos cuantos elementos a la vez a la GPU. Si no se especifica nada, los mini-lotes son de 64 elementos, que van a parar al mismo tensor a la vez. Figura 5.26: Código red neuronal 4 5. Por último, se crea un learner, utilizando una red preentrenada (lo que se hace aquí es transfer learning, es decir, que reentrenamos una red ya entrenada, preparada para clasificar imágenes), llamada resnet18 (porque tiene 18 capas ocultas), y vamos a mostrar la tasa de error (el error_rate). Con el fine_tune mostramos el número de épocas de entrenamiento, en este caso, 20. 74 ANÁLISIS DEL CLASIFICADOR Figura 5.27: Código red neuronal 5 6. A estas alturas, la red neuronal ya está creada, y como puede comprobarse, acierta el 100% de las imágenes (tiene un 0% de tasa de error). A partir de aquí, vamos a obtener datos de nuestro interés. Mostramos en una matriz el número de imágenes “Soldadura_Buena” que el clasificador ha sido capaz de clasificar como “Soldadura_Buena” y el número de imágenes “Soldadura_Buena” que el clasificador ha clasificado erróneamente como “Soldadura_Mala”, y lo mismo con las imágenes que eran “Soldadura_Mala”. A esta matriz se la llama matriz de confusión. El resultado que obtenemos, en este caso, es el siguiente: Figura 5.28: Código red neuronal 6 75 ANÁLISIS DEL CLASIFICADOR 7. Por último, un dato muy importante a la hora de pulir una red neuronal es saber en qué imágenes, la red ha tenido más dudas a la hora de clasificarlas. El resultado de la clasificación de una imagen utilizando la red neuronal es un tensor de dos valores, cuya suma es siempre 1. Cada número expresa la probabilidad de que la imagen sea de un tipo u otro. De esta manera, por ejemplo, si el primer número representa la categoría “Soldadura_Buena” y el segundo representa la categoría “Soldadura_Mala”, un tensor [0.996353, 0.003647], indica que con una probabilidad del 99,63 % según la red, la imagen está representando una Soldadura_Buena. Existe una función en fastai llamada top_loses, que te devuelve una lista con el nombre de las imágenes que menor tensor han tenido, es decir, que más cercanas están del 50 %, y más lejanas del 100 %. Es muy sencillo de entender el código que se ha utilizado para mostrar esta información para las 125 imágenes que menor tensor tienen. Figura 5.29: Código red neuronal 7 5.5. Experimentación Una vez hemos entendido el código que se va a utilizar para generar las redes neuronales (en todas va a ser el mismo código cambiando la ruta de las imágenes), vamos a exponer los diferentes experimentos que hemos realizado para ir puliendo el dataset. En esta tabla, se han introducido las tasas de error de cada tipo con el primer dataset: 76 EVALUACIÓN DEL APRENDIZAJE Las estrategias de experimentación que se van a realizar son las siguientes: A. Se entrenará desde cero el mismo dataset, incluyendo las imágenes de la nueva soldadura, a la que se la aplicarán algunas transformaciones para que tenga más peso sobre el resto de imágenes del dataset. En total, se introducirán 16 imágenes similares. B. Se reentrenará la red generada en el experimento base, utilizando tan solo imágenes de la nueva soldadura, a la que también se la aplicarán algunas transformaciones. En total, se introducirán 64 imágenes similares. C. Se reentrenará la red generada en el experimento base, incluyendo en el dataset las imágenes de la nueva soldadura, a la que también se la aplicarán algunas transformaciones para que tenga más peso sobre el resto de las imágenes del dataset. En total, se introducirán 64 imágenes similares. D. Se reentrenará la red generada en el experimento base, incluyendo en el dataset las imágenes de la nueva soldadura, a la que también se la aplicarán algunas transformaciones para que tenga más peso sobre el resto de las imágenes del dataset. En este caso, sin embargo, se dará mucho más peso a la nueva imagen, y se realizará un augmentation lo suficientemente grande como para que en torno al 10 % del dataset contenga imágenes relacionadas con esta. En total, se introducirán 600 imágenes similares. E. Se entrenará desde cero el dataset utilizado para el apartado D. Las imágenes similares que se introducirán en los datasets, estarán creadas a partir de la nueva imagen que no es capaz de clasificar correctamente, a la que se la modificarán en la mitad de estas nuevas imágenes un 2 % de los píxeles, los cuales se “pintarán” de negro, y a la otra mitad, se modificará su intensidad (que recordemos que estaba formada por números comprendidos entre el 0 y el 255), en un número aleatorio entre el -5 y el +5. Además, para cada uno de los casos se realizará lo siguiente: Se generarán los resultados y se compararán con los resultados del experimento base. Se generarán gráficos en los que se mostrará la tasa de error y la exactitud de la red. Se enunciarán las conclusiones. 83 EVALUACIÓN DEL APRENDIZAJE En resumen, lo que se va a realizar para cada una de las imágenes que se pretenden estudiar es lo siguiente: Figura 6.1: Resumen de los experimentos 6.4. Experimentación. Análisis de aprendizaje sobre soldaduras sencillas Para la realización de estos experimentos, se va a utilizar una red obtenida de un dataset del que se obtiene una tasa de error de un 0 %, por lo que se esperan buenos resultados en poco tiempo. 6.4.1. Experimento 1 Para el primer experimento se va a utilizar la siguiente imagen, que representa una soldadura mala, y esta imagen no estaba incluida en el dataset que ha entrenado la red: Figura 6.2: Ejemplo soldadura experimento 1 84 EVALUACIÓN DEL APRENDIZAJE 6.4.1.1. Caso base En el caso base utilizamos solo la base de datos original. Los datos obtenidos se pueden ver resumidos en la siguiente gráfica: Figura 6.3: Gráfica de datos, experimento 1, caso base Y la salida que obtenemos al predecir la clasificación de esta imagen con esta red es la siguiente: Figura 6.4: Resultado experimento 1 caso base Lo que significa que la red predice que esta imagen representa una soldadura buena (sin defectos). Esto nos indica que la red tiene que ser reentrenada. 85 EVALUACIÓN DEL APRENDIZAJE 6.4.1.2. Caso A En el caso A se utilizará la base de datos del caso base, a la que se le añadirán 16 imágenes derivadas de la imagen que queremos clasificar, y esto se entrenará desde cero. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.5: Gráfica de datos, experimento 1, caso A Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene la tasa de error. En este caso, el resultado de la predicción de la imagen es el siguiente: Figura 6.6: Resultado experimento 1, caso A Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala que se clasifica correctamente, con bastante seguridad (más de un 99.99 %). 86 EVALUACIÓN DEL APRENDIZAJE 6.4.1.3. Caso B En el caso B se utilizarán 64 imágenes derivadas de la imagen que queremos clasificar. Este dataset se utilizará para reentrenar la red del caso base. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.7: Gráfica de datos, experimento 1, caso B Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene la tasa de error. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.8: Resultado experimento 1 caso B Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, por lo que se clasifica correctamente, con bastante seguridad (más de un 99.99 %). 87 EVALUACIÓN DEL APRENDIZAJE 6.4.1.4. Caso C En el caso C se utilizará la base de datos del caso base, a la que se le añadirán 16 imágenes derivadas de la imagen que queremos clasificar. Este dataset se utilizará para reentrenar la red del caso base. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.9: Gráfica de datos, experimento 1, caso C Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene la tasa de error. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.10: Resultado experimento 1 caso C Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, es decir, que la clasifica correctamente. Además, con bastante seguridad (más de un 99.99 %). 88 EVALUACIÓN DEL APRENDIZAJE 6.4.1.5. Caso D En el caso D se utilizará la base de datos del caso base, a la que se le añadirán 600 imágenes derivadas de la imagen que queremos clasificar. Este dataset se utilizará para reentrenar la red del caso base. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.11: Gráfica de datos, experimento 1, caso D Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene la tasa de error. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.12: Resultado experimento 1 caso D Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, es decir, que la clasifica correctamente. Además, con bastante seguridad (más de un 99.99 %). 89 EVALUACIÓN DEL APRENDIZAJE 6.4.1.6. Caso E En el caso E se utilizará la base de datos del caso base, a la que se le añadirán 600 imágenes derivadas de la imagen que queremos clasificar, y esto se entrenará desde cero. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.13: Gráfica de datos, experimento 1, caso E Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene la tasa de error. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.14: Resultado experimento 1 caso E 90 EVALUACIÓN DEL APRENDIZAJE Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, es decir, que la clasifica correctamente. Además, con bastante seguridad (más de un 99.99 %). El resumen del experimento 1 ha sido el siguiente: Figura 6.15: Resumen experimento 1 6.4.2. Experimento 2 Para el segundo experimento se va a utilizar la siguiente imagen, que representa una soldadura mala, y esta imagen no estaba incluida en el dataset que ha entrenado la red: Figura 6.16: Ejemplo soldadura experimento 2 91 EVALUACIÓN DEL APRENDIZAJE 6.4.2.1. Caso base En el caso base utilizamos solo la base de datos original. Los datos obtenidos se pueden ver resumidos en la siguiente gráfica: Figura 6.17: Gráfica de datos, experimento 2, caso base Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene la tasa de error. Y la salida que obtenemos al predecir la clasificación de esta imagen con esta red es la siguiente: Figura 6.18: Resultado experimento 2 caso base Lo que significa que la red predice que esta imagen representa una soldadura buena (sin defectos), y no es así. Esto nos indica que la red tiene que ser reentrenada. 92 EVALUACIÓN DEL APRENDIZAJE 6.5.1.1. Caso base En el caso base utilizamos solo la base de datos original. Los datos obtenidos se pueden ver resumidos en la siguiente gráfica: Figura 6.31: Gráfica de datos, experimento 1, caso base Y la salida que obtenemos al predecir la clasificación de esta imagen con esta red es la siguiente: Figura 6.32: Resultado experimento 1 caso base Lo que significa que la red predice que esta imagen representa una soldadura buena (sin defectos). Esto nos indica que la red tiene que ser reentrenada. 99 EVALUACIÓN DEL APRENDIZAJE 6.5.1.2. Caso A En el caso A se utilizará la base de datos del caso base, a la que se le añadirán 16 imágenes derivadas de la imagen que queremos clasificar, y esto se entrenará desde cero. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.33: Gráfica de datos, experimento 1, caso A Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene una tasa de error similar. En este caso, el resultado de la predicción de la imagen es el siguiente: Figura 6.34: Resultado experimento 1, caso A Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala que se clasifica correctamente, con bastante seguridad (más de un 99.99 %). 100 EVALUACIÓN DEL APRENDIZAJE 6.5.1.3. Caso B En el caso B se utilizarán 64 imágenes derivadas de la imagen que queremos clasificar. Este dataset se utilizará para reentrenar la red del caso base. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.35: Gráfica de datos, experimento 1, caso B En este caso no podemos saber si la red ha perdido o ganado tasa de error. Con los resultados obtenidos, la tasa de error se obtiene del dataset introducido, formado por 64 imágenes, por lo que el resultado no es comparable. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.36: Resultado experimento 1 caso B Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, por lo que se clasifica correctamente, con bastante seguridad (más de un 99.99 %). 101 EVALUACIÓN DEL APRENDIZAJE 6.5.1.4. Caso C En el caso C se utilizará la base de datos del caso base, a la que se le añadirán 16 imágenes derivadas de la imagen que queremos clasificar. Este dataset se utilizará para reentrenar la red del caso base. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.37: Gráfica de datos, experimento 1, caso C Lo que nos indica que ha habido sobreentrenamiento, y pese a que la tasa de error sea menor que en el caso base, ha sido mejor en épocas anteriores. De todas maneras, las tasas de error no varían lo suficiente como para tenerlas en cuenta, ni de manera positiva ni de manera negativa. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.38: Resultado experimento 1 caso C Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, es decir, que la clasifica correctamente. Además, con bastante seguridad (más de un 99.99 %). 102 EVALUACIÓN DEL APRENDIZAJE 6.5.1.5. Caso D En el caso D se utilizará la base de datos del caso base, a la que se le añadirán 600 imágenes derivadas de la imagen que queremos clasificar. Este dataset se utilizará para reentrenar la red del caso base. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.39: Gráfica de datos, experimento 1, caso D Lo que nos indica que ha habido sobreentrenamiento, y pese a que la tasa de error sea menor que en el caso base, ha sido mejor en épocas anteriores. De todas maneras, las tasas de error no varían lo suficiente como para tenerlas en cuenta, ni de manera positiva ni de manera negativa. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.40: Resultado experimento 1 caso D Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, es decir, que la clasifica correctamente. Además, con bastante seguridad (más de un 99.99 %). 103 EVALUACIÓN DEL APRENDIZAJE 6.5.1.6. Caso E En el caso E se utilizará la base de datos del caso base, a la que se le añadirán 600 imágenes derivadas de la imagen que queremos clasificar, y esto se entrenará desde cero. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.41: Gráfica de datos, experimento 1, caso E Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que mantiene la tasa de error. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.42: Resultado experimento 1 caso E Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, es decir, que la clasifica correctamente. Además, con bastante seguridad (más de un 99.99 %). 104 EVALUACIÓN DEL APRENDIZAJE El resumen del experimento 1 ha sido el siguiente: Figura 6.43: Resumen experimento 1 6.5.2. Experimento 2 Para el segundo experimento se va a utilizar la siguiente imagen, que representa una soldadura mala, y esta imagen no estaba incluida en el dataset que ha entrenado la red: Figura 6.44: Ejemplo soldadura experimento 2 105 EVALUACIÓN DEL APRENDIZAJE 6.5.2.1. Caso base En el caso base utilizamos solo la base de datos original. Los datos obtenidos se pueden ver resumidos en la siguiente gráfica: Figura 6.45: Gráfica de datos, experimento 2, caso base Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que se mantiene la tasa de error. Y la salida que obtenemos al predecir la clasificación de esta imagen con esta red es la siguiente: Figura 6.46: Resultado experimento 2 caso base Lo que significa que la red predice que esta imagen representa una soldadura buena (sin defectos), y no es así. Esto nos indica que la red tiene que ser reentrenada. 106 EVALUACIÓN DEL APRENDIZAJE 6.5.2.2. Caso A En el caso A se utilizará la base de datos del caso base, a la que se le añadirán 16 imágenes derivadas de la imagen que queremos clasificar, y esto se entrenará desde cero. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.47: Gráfica de datos, experimento 2, caso A Lo que no supone una bajada en el rendimiento con respecto al caso base, ya que se mantiene la tasa de error. En este caso, el resultado de la predicción de la imagen es el siguiente: Figura 6.48: Resultado experimento 2, caso A Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala que se clasifica correctamente, con bastante seguridad (más de un 99.99 %). 107 EVALUACIÓN DEL APRENDIZAJE 6.5.2.3. Caso B En el caso B se utilizarán 64 imágenes derivadas de la imagen que queremos clasificar. Este dataset se utilizará para reentrenar la red del caso base. El gráfico que muestra la tasa de error, la función de optimización y función de pérdida en función de la época de entrenamiento es el siguiente: Figura 6.49: Gráfica de datos, experimento 2, caso B En este caso no podemos saber si la red ha perdido o ganado tasa de error. Con los resultados obtenidos, la tasa de error se obtiene del dataset introducido, formado por 64 imágenes, por lo que el resultado no es comparable. Después de reentrenar la red del caso base, el resultado de la predicción de la imagen es el siguiente: Figura 6.50: Resultado experimento 2 caso B Como puede observarse, la predicción en este caso es que la imagen es una soldadura mala, por lo que se clasifica correctamente, con bastante seguridad (más de un 99.99 %). 108 BIBLIOGRAFÍA Bibliografía [Nie] Michael Nielsen. Neural networks and deep learning. http:// neuralnetworksanddeeplearning.com/. [pro] proyectosagiles. Proyectos agiles scrum. https://proyectosagiles.org/ que-es-scrum/. [Syl] Jeremy y Alexis Gallaghe Sylvain. Manual fastai fastbook. https:// github.com/fastai/fastbook. [ven] venngage. Definición diagrama de gantt. https://es.venngage.com/ blog/ejemplos-diagramas-gantt-plantillas/. [Wika] Wikipedia. Anaconda. https://es.wikipedia.org/wiki/Anaconda_ (distribuci%C3%B3n_de_Python). [Wikb] Wikipedia. Michael nielsen. https://es.wikipedia.org/wiki/Michael_ Nielsen. [Wikc] Wikipedia. Perceptron. https://es.wikipedia.org/wiki/Perceptr%C3% B3n. [Wikd] Wikipedia. Red neuronal artificial. https://es.wikipedia.org/wiki/ Red_neuronal_artificial. [Wike] Wikipedia. Sobreajuste. https://es.wikipedia.org/wiki/Sobreajuste. [Wikf] Wikipedia. Soldadura. https://es.wikipedia.org/wiki/Soldadura. 115