Capitulo 6 6 Data Augmentation y Transfer Learning del libro Keras TensorFlow

Data Augmentation y Transfer Learning

 

Contenido abierto del Capítulo 6 del libro DEEP LEARNING Introducción práctica con Keras

Este post es una versión preliminar del capítulo 6 del libro “Deep Learning – Introducción práctica con Keras (SEGUNDA PARTE)” que se publicará este otoño en Kindle Direct Publishing con ISBN 978-1-687-47399-8 en la colección WATCH THIS SPACE – Barcelona (Book 6). Como autor agradeceré que cualquier error o comentario que el lector o lectora encuentre en este texto me lo comunique por email a libro.keras@gmail.com para mejorar su contenido. Muchas gracias de antemano.

En este capítulo presentaremos DataAugmentation, una de las técnicas para mitigar el sobreajuste en los modelos de redes neuronales. En nuestro caso de estudio, esta técnica mejorará el modelo anterior que presentaba una Accuracy de 73.9%, alcanzando una Accuracy de 80.1%.

A continuación introduciremos dos variantes de la técnica llamada Transfer Learning que nos permitirán mejorar aún más el modelo anterior. Primero presentaremos la técnica FeatureExtraction usando una red preentrenada que nos llevará a una Accuracy de 90.4% y después la técnica Fine-Tuning de una red preentrenada que nos llevará a una Accuracy del 93.1%.

6.1 Data Augmentation  

Cuantos menos datos tengamos, menos datos para entrenar y menos posibilidades tendremos de obtener predicciones precisas para datos que nuestro modelo aún no ha visto. Data Augmentation adopta el enfoque de generar más datos de entrenamiento a partir de nuestros datos disponibles. En el caso de imágenes, esto lo consigue aplicando una serie de transformaciones aleatorias a la imagen que producen nuevas imágenes de aspecto creíble. El objetivo es que en el momento del entrenamiento, nuestro modelo nunca verá exactamente la misma imagen en las diferentes epochs. Esta idea simple, pero potente, ayuda a exponer el modelo a más aspectos de los datos y a generalizar mejor.

Transformaciones de imágenes

Esta técnica es especialmente poderosa para datos de tipo imagen pero a la vez muy simple, ya que aplica transformaciones sencillas (rotar, voltear…) a las imágenes para obtener de nuevas plausibles, que podrían estar en el conjunto de datos original. No obstante, debe tenerse cuidado con la elección de las técnicas específicas de aumento de datos utilizadas, teniendo en cuenta el contexto del conjunto de datos de entrenamiento y el conocimiento del dominio del problema, para no generar imágenes que nunca podrían encontrarse en realidad ya que de esta manera estaríamos empeorando el entrenamiento.

En Keras, esto se puede hacer de manera muy fácil mediante la configuración de una serie de transformaciones que se realizarán en las imágenes leídas por la instancia de ImageDataGenerator. Para obtener información detallada sobre las transformaciones disponibles puede consultar la API de preprocessingde Keras[1].

Es importante resaltar que se realiza la transformación de manera onlinedurante el procesamiento, permitiendo hacer el proceso automático mientras se realiza el entrenamiento sin necesidad de modificar los datos almacenados en disco. Así el modelo ve una imagen generada aleatoriamente una sola vez. Evidentemente, estas transformaciones se podrían realizar previamente e incluirlas en el conjunto de datos de entrenamiento. De esta manera el preprocesado resultaría más rápido, puesto que no se realizarían las transformaciones en tiempo de ejecución, pero en cambio el espacio de almacenamiento y el tiempo de carga de los datos en memoria serían más elevados.

Configuración de ImageGenerator

Cogiendo de base el modelo presentado en el capítulo anterior, apliquemos la técnica Data Augmentation pasando nuevos argumentos al objeto ImageGeneratorde los datos de entrenamiento. Hay varios parámetros, nosotros hemos elegido los siguientes para nuestro caso de estudio:

Una explicación breve de cada uno de ellos es la siguiente:

  • rotation_rangees un valor en grados (0–180) que indica el rango dentro del cual se pueden rotar imágenes al azar.
  • width_shifty height_shift son rangos (como una fracción del ancho y la altura total) dentro de los cuales se pueden trasladar las imágenes al azar verticalmente u horizontalmente.
  • shear_rangesirve para aplicar transformaciones de corte al azar.
  • zoom_rangesirve para aplicar zoomaleatorio dentro de las imágenes.
  • horizontal_flipes para voltear aleatoriamente la mitad de las imágenes horizontalmente (en nuestro caso de estudio no tiene sentido voltear verticalmente las imágenes).
  • fill_modees la estrategia utilizada para rellenar los píxeles recién creados que pueden aparecer después de una de las transformaciones anteriores.

Estas son solo algunas de las opciones disponibles de transformación, pudiéndose consultar todas las restantes en la página web de la API de preprocessing de Keras[2].

Para comprobar con más detalle cómo funciona cada una de las opciones, propongo al lector que use el siguiente código como base para hacer pruebas:

En concreto este código muestra como se genera aleatoriamente nuevas imágenes usando un rango de 45% de rotación indicados con el argumento rotation_range. Por ejemplo, podemos probar con la imagen de Wiliams, el gato de nuestros amigos Paco y Mónica. La ejecución del anterior código para la imagen de Wiliams nos devuelve las siguientes imágenes:

keras-tensorflow-data-augmentation : ejemplo transformaciones gato wiliams

Podemos ver como se han generado diferentes imágenes aleatoriamente a partir de la imagen original y en base al argumento rotation_range.El lector puede por su cuenta probar otros argumentos usando este código como base.

Código del caso de estudio

Es importante resaltar que el aumento de datos de imagen generalmente solo se aplica al conjunto de datos de entrenamiento, y no al conjunto de datos de validación o prueba. Esto es diferente de la preparación de datos, como el cambio de tamaño de la imagen y la escala de píxeles. Teniendo en cuenta esto, los generadores para nuestro caso de estudio se pueden especificar de la siguiente forma:

keras-tensorflow-data-augmentation: codigo generadores

Para el resto de hiperparámetros tanto para la compilación como el entrenamiento del modelo usaremos los mismos que en el anterior capítulo:

El lector debe tener en cuenta que con 100 epochs (los que tenemos en el código del GitHub por defecto) se requerirá más de una hora para finalizar el entrenamiento[3], puede probar con menos:

Una vez finalizada el entreno de la red neuronal, podemos usar el mismo código que el del anterior capítulo para visualizar la evolución del entrenamiento. El resultado será el mostrado en las dos gráficas siguientes:

keras-tensorflow-data-augmentation: grafica evolución accuracy

keras-tensorflow-data-augmentation: grafica evolución loss

Como podemos observar, el haber aplicado Data Augmentation ha paliado parcialmente el Overfitting que teníamos en nuestro caso de estudio, puesto que las dos curvas de Accuracy siguen la misma línea hasta aproximadamente la epoch 60 donde empiezan a divergir. Además, si calculamos el comportamiento con los datos de prueba vemos que se ha mejorado el modelo anterior que presentaba una Accuracy de 73.9%, alcanzando ahora una Accuracy 80,1%:

keras-tensorflow-data-augmentation: model evaluate

En resumen, en esta sección hemos examinado esta técnica realmente útil, que Keras ofrece en su paquete, para simular efectivamente un conjunto de datos más grande para entrenar la red neuronal y poder de esta manera reducir el problema de Overfitting.

Pero aun así las entradas que ve la red neuronal todavía están muy correlacionadas, ya que provienen de una pequeña cantidad de imágenes originales: no puede producir nueva información, solo puede mezclar la información existente. Como tal, esto puede no ser suficiente para deshacerse por completo del Overfitting en algunos casos. Para seguir luchando para mitigar el Overfitting, hay más técnicas como la regularización[4] o Dropout[5] que luego comentamos, pero que queda fuera del ámbito que habíamos previsto para este libro el entrar en explicarlas con detalle. Pero incluso así a veces debido a no tener más datos, no es suficiente para obtener mejores modelos. Para estos casos aun nos queda otra oportunidad, usar modelos preentrenados que presentamos en la siguiente sección.

 

6.2 Transfer Learning

En la sección anterior, vimos cómo aminorar el efecto de un sobreajuste de un modelo con una técnica muy útil para imágenes como es Data Augmentation. Pero en realidad nos encontramos limitados en cuanto a descubrir características de los datos, puesto que si los datos de entrenamiento son muy pocos, al hacer transformaciones con la técnica de Data Augmentation parte de las características de las nuevas imágenes son repeticiones de las anteriores. ¿Qué pasaría si se pudiera tomar un modelo existente que está ya entrenado en muchos más datos y usar las características que ese modelo aprendió para aplicarlo a nuestros datos? Ese es el concepto de Transfer Learning y es lo que exploraremos en esta sección.

Concepto de Transfer Learning

Transfer Learninges una de las técnicas más importantes de Deep Learning. Su interés radica en que en lugar de necesitar entrenar una red neuronal desde cero, que implica quizás precisar de una gran cantidad de datos y requerir mucho tiempo (días o semanas) de computación para entrenar, lo hacemos desde una red preentrenada. Esta técnica nos permite descargar un modelo de código abierto que alguien ya ha entrenado previamente en un gran conjunto de datos y usar sus parámetros (miles o millones) como punto de partida para posteriormente continuar entrenando el modelo con el conjunto de datos (más pequeño) que tengamos para una tarea determinada.

Si el conjunto de datos original con el que se entrenó la red neuronal preentrenada es suficientemente grande y general, entonces la jerarquía espacial de las características (features) aprendidas por la red preentrenada permite al modelo preentrenado actuar como un modelo genérico del mundo visual y, por lo tanto, sus características pueden resultar útiles para muchos problemas diferentes de visión por computadora, a pesar de que estos nuevos problemas pueden involucrar clases completamente diferentes a las de la tarea original.

Si volvemos al sencillo ejemplo visual que presentábamos en el capítulo 4, recordaremos que en una red neuronal convolucional cada capa va aprendiendo diferentes niveles de abstracción siendo las primeras capas las encargadas de aprender características más genéricas.

keras-tensorflow-transfer-learning diagrama de capas deep learning

Estas primeras son las capas que podemos volver a usar fácilmente puesto que las características aprendidas son aplicables a otros problemas. Esta “portabilidad” de las características aprendidas a través de diferentes problemas es unas virtudes clave del transfer learning.

Específicamente, en el caso de la visión por computador, muchos modelos previamente entrenados (muchos entrenados en el conjunto de datos ImageNet) ahora están disponibles públicamente para su descarga y se pueden usar para crear potentes modelos de visión con muy pocos datos. Esto es lo que vamos a hacer a continuación a nivel de código con un modelo muy popular llamado VGG16, que ya presentamos en la sección 4.5 (de la PRIMERA PARTE del libro) y se ha entrenado previamente en un conjunto de datos de ImageNet.

Hay dos formas de utilizar una red preentrenada que presentamos a continuación: Feature Extractiony Fine-Tuning.

Feature Extraction 

Feature Extractionconsiste en utilizar los parámetros aprendidos por una red preentrenada para extraer características interesantes de nuevos datos. Estas características (features)obtenidas de los nuevos datos se procesan a través de un nuevo clasificador, que se entrena desde cero.

Ya vimos en el capítulo 4 que las ConvNet utilizadas para clasificar imágenes se componían de dos partes: primero una serie de capas de convoluciones y pooling, terminando con un clasificador fully-connected. La primera parte se llama base convolucional (convolutional base) del modelo. En el caso de las ConvNet, la extracción de características consiste en tomar la base convolucional de una red previamente entrenada, ejecutar los nuevos datos a través de ella y entrenar a un nuevo clasificador en la parte de la salida.

En la siguiente figura se muestra de forma esquemática esta idea. A la izquierda se muestra una ConvNet resaltando sus dos partes, la compuesta por las capas convolucionales y de pooling, y el clasificador final. En la figura del medio resaltamos que de esta ConvNet de base, desechamos las capas finales de clasificación y nos quedamos con la primera parte, tanto su estructura de capas como los valores de los parámetros (pesos y sesgos de sus neuronas) que llamamos base convolucional. Finalmente, en la figura de la derecha se representa la estructura de la ConvNet que usaremos para clasificar nuestros nuevos datos. A la base convolucional que ya se encuentra entrenada le añadimos las capas finales que se requieran para hacer el clasificador a nuestra medida del problema que estamos tratando. Recordemos que este nuevo clasificador sí que requiere entrenamiento (en general los pesos de sus parámetros se han iniciado de forma aleatoria).

keras-tensorflow-transfer-learning esquema de uso base convolucional entrenada

Recordemos que resulta muy útil reutilizar la base convolucional porque las características aprendidas por la red preeentrenada de donde se ha extraído son mapas de características de conceptos genéricos sobre una imagen, lo que en general resulta “portable” a otros problema del mismo ámbito.

Pero en general no se reutiliza el clasificador entrenado (fully-connected), ya que las representaciones aprendidas por el clasificador serán necesariamente específicas del conjunto de clases en las que se formó el modelo; solo contendrán información sobre la probabilidad de presencia de esta o aquella clase en la imagen completa. Además, las representaciones encontradas en capas densamente conectadas ya no mantienen información sobre dónde se encuentran los objetos en la imagen de entrada porque estas capas eliminan la noción de espacio, a diferencia de las capas que vimos en el capítulo 4.

Lo más interesante para nosotros ahora es que librerías como Keras (y TensorFlow) nos permiten aplicar esta técnica de una manera muy fácil y con pocas líneas de código. Keras permite descarga un modelo y luego se configura cómo este debe ser entrenado, indicando qué capas son entrenables (trainable layers) y qué capa no (frozen layers). En general se requiere unas cuantas iteraciones de prueba y error para descubrir la combinación correcta.

Concretamente en el caso de visión por computador, muchos modelos preentrenados con ImageNet se encuentran disponibles en la mayoría de entornos de desarrollo de Deep Learning, como es el caso de Keras. En concreto en la página de modelos preentrenadosde tf.keras.applications[6] podemos encontrar disponibles los siguientes modelos para clasificación de imágenes entrenados con ImageNet:

  • Xception
  • VGG16
  • VGG19
  • ResNet50
  • InceptionV3
  • InceptionResNetV2
  • MobileNet
  • MobileNetV2
  • DenseNet
  • NASNet

En nuestro ejemplo ya hemos avanzado que usaremos la red neuronal VGG16, que tiene una arquitectura convolucional como las que hemos comentado en los capítulos previos. Muchas de las otras redes preentrenadas disponibles, cuyos investigadores han mejorado los resultados en ImageNet, no siguen una estructura secuencial de capas como las que hemos visto hasta ahora y requieren usar la API de Keras que trataremos en el capítulo 8 del libro. Por este motivo nos hemos decantado para usar VGG16 para explicar está técnica.

La red neuronal VGG16 se ha entrenado previamente en un conjunto de datos de ImageNet, que recordemos que tiene 1,4 millones de imágenes en 1000 clases diferentes. ImageNet contiene muchas clases de animales, incluidas diferentes especies de gatos y perros, por lo que podemos esperar un buen rendimiento en el problema de clasificación de perros contra gatos. Recordemos que el modelo VGG16 es una red de 16 capas propuesto por Karen Simonyan y Andrew Zisserman en su artículo ‘Very Deep Convolutional Networks for Large-Scale Image Recognition’[7]. Más adelante entraremos en más detalle sobre sus capas.

El modelo VGG16, entre otros, viene preempaquetado con Keras. Podemos importarlo desde el módulo keras.applications:

keras-tensorflow-transfer-learning codigo VGG16

A este constructor de la red VGG16 se le pasan tres argumentos. El primero es la forma de los tensores de imágenes que alimentarán a la red (es un argumento opcional). El segundo es el argumento include_topdonde se indica si se debe incluir (o no) el clasificador en la última capa de la red. En este caso de VGG16 esta capa corresponde a la capa que clasifica las 1000 clases de ImageNet. Debido a que tenemos la intención de usar nuestro propio clasificador (que clasifica solo dos clases: gato y perro), no necesitamos incluirla. El último argumento weightsindica de dónde se obtiene la información para iniciar los pesos de los parámetros de la red (en nuestro caso usaremos ImageNet).

Recordemos que con el método .summary( ) podemos saber el detalle de la arquitectura de la base convolucional VGG16:

keras-tensorflow-transfer-learning vgg16 summary

El lector puede comprobar que las capas de esta base convolucional le resultan familiares, pues son todas ellas convolucionales o poolingcomo las estudiadas en el capítulo 4. Si comparamos con una red neuronal VGG16, que introducimos en la sección 4.5, podemos comprobar que no existen las dos capas finales fully-connected de 4096 neuronas y la de 1000 neuronas (cada una de estas neuronas representa una de las categorías de imágenes de ImageNet), las cuales hemos decidido no incluir con el valor Falsedel argumento include_top. Insistimos en que no necesitamos las últimas tres capas (que son el clasificador de VGG16) porque crearemos unas propias para construir nuestro clasificador y predecir si las imágenes serán un perro o un gato a partir del último feature mapde forma y tamaño (4,4,512)que nos devuelve la base convolucional VGG16.

Antes de entrenar el modelo, es muy importante indicar que las capas de la base convolucional no deben ser entrenadas, lo que se denomina “congelar” capas, (freeze layers). Congelar una capao un conjunto de capas significa evitar que sus pesos se actualicen durante el entrenamiento. Si no hiciéramos esto, los valores que fueron previamente aprendidos por la base convolucional serían modificados durante el entrenamiento, efecto que no buscamos. En Keras, congelar una capa se realiza estableciendo su atributo trainablea False:

En Keras los modelos los podemos considerar como capas, y por tanto podemos agregar un modelo (como pre_trained_model) a un modelo secuencial al igual que agregaríamos una capa:

Así es como el método summary() nos presenta que acabamos de construir:

Summary del modelo Feature Extraction

Como puede ver el lector, la base convolucional de VGG16 tiene 14,714,688 parámetros, que es muy grande. Pero fijémonos que ahora no se entrenan estos parámetros (está indicado en la última línea con la etiqueta Non-trainable params que hasta ahora siempre la habíamos visto a0), y que el clasificador que estamos agregando en la parte final tiene unos 2 millones de parámetros que sí son entrenables. En realidad, se trata de un clasificador más simple que el que tenia por defecto VGG16 y si comparamos con las capas densas que conforman el clasificador originales de VGG16 (ver sección 4.5) vemos que el número de parámetros es mucho menor (antes era más de 100 millones).

Una vez definida nuestra red nos queda compilarla, usando los mismos argumentos que antes:

Ahora ya podemos comenzar a entrenar el modelo con el método fit_generator(), con la misma configuración de Data Augmentationque utilizamos en la sección anterior. Pero no es necesariamente siempre la mejor opción y depende del tipo y cantidad de datos disponibles cuál es la mejor combinación de técnicas. Como ya hemos indicado en anteriores ocasiones en este libro, se trata de ir avanzando con prueba y error en la mayoría de casos (el lector puede probar sin Data Augmentation)[8]:

keras-tensorflow-transfer-learning entrenar modelo feature extraction

Podemos comprobar que con los datos de Test obtenemos una Accuracy de 90.4%, mucho mejor que en el modelo de la sección anterior que consiguió un 80.1% de Accuracy:

keras-tensorflow-transfer-learning test modelo feature extraction

Igual que hemos hecho con el anterior modelo, con este también podemos mostrar gráficamente la evolución de las métricas de rendimiento durante el entrenamiento con estas dos gráficas:

keras-tensorflow-transfer-learning grafica comportamiento accuracy modelo feature extraction

keras-tensorflow-transfer-learning grafica comportamiento loss modelo feature extraction

En la primera gráfica con la evolución de la Accuracy vemos que tenemos una Accuracy tanto para los datos de entrenamiento como los de validación mucho mejores que en el modelo de la anterior sección (fíjense que el rango del eje de las Y son diferentes) tal como ya indica la Accuracy aplicada a los datos de Test. Ahora bien, llega un momento en el que a partir de un número de epochsel modelo empieza a presentar Overfitting, dando señales que ya no puede pasar de esta Accuracy con los datos y modelo disponible. En realidad esta situación se observa perfectamente a partir de unaepochpróxima a 40 en la gráfica de Losscuando las dos líneas empiezan a divergir.

Una observación en la que quizás algún lector se fije es que con pocas epochsel modelo empieza a adaptase mejor a los datos de validación que a los de entrenamiento. Este es un fenómeno puntual de inicio de entreno, sin consecuencias en la Accuracy del modelo y es debido a que los datos de Training, al aplicar Data Augmentation, en las primeras iteraciones los datos que el modelo ve para entrenar cada vez son nuevos y el modelo le cuesta un poco más adaptarse a estos datos que a los datos más generales de validación.

Fine Tuning 

Otra técnica ampliamente utilizada en la reutilización de modelos, complementaria a la Feature Extraction, es Fine-Tuning, que consiste en hacer un ajuste más fino y entrenar también algunas de las capas finales de la base convolucional del modelo usado para la extracción de características (que hasta ahora se mantenía congelado), y entrenar conjuntamente tanto la parte agregada del clasificador como estas capas. Esto se llama Fine-Tuning en nuestro entorno porque se trata de un “ajuste fino” de las representaciones más abstractas del modelo que se está reutilizando como base.

Recordemos que el nivel de “generalidad” y, por lo tanto, de reutilización de las representaciones extraídas por capas de convolución específicas depende de la posición de la capa en el modelo. Las primeras capas aprenden características generales y después gradualmente en capas sucesivas se van aprendiendo características más concretas del dominio de problema que estamos tratando. En concreto, las capas del modelo que están más próximas a la capa de entrada de datos extraen mapas de características locales altamente genéricas, mientras que las capas que están más cerca del clasificador final extraen conceptos más abstractos.

Para expresar más gráficamente el concepto, en nuestro ejemplo de gatos y perros podríamos imaginarnos que las capas más iniciales extraen bordes, texturas, colores, etc. Las capas del medio extraen conceptos más abstractos como “oreja” u “ojo”. Y las capas que están casi al final conceptos aun más abstractos como «oreja de perro» u «ojo de gato», con los que las capas finales pueden construir “perro”o “gato”.

Por lo tanto, si el nuevo conjunto de datos que queremos clasificar difiere mucho del conjunto de datos en el que se entrenó el modelo original, se deben usar solo las primeras capas del modelo para realizar la extracción de características, en lugar de usar toda la base convolucional. Como antes, hay un cierto prueba y erroren todo el proceso basado sobretodo en la experiencia del desarrollador que se encuentra delante del teclado.

Volviendo a nuestro código del caso de estudio, si nos fijamos en el nombre que se le asigna a las capas en la base convolucional VGG16 vemos que se compone de 5 bloques: block1, block2, block3, block4, block5.

Para mostrar al lector la técnica de Fine-Tuning proponemos que en esta sección entrenemos también el block5compuesto por tres capas convolucionalesy una de pooling  (block5_conv1, block5_conv2, and block5_conv3serán ahora entrenables[9]).

El código en Keras (Python) que nos permite especificar este comportamiento en la fase de entrenamiento que acabamos de describir puede ser el siguiente:

keras-tensorflow-transfer-learning congelación congelacion capas de VGG16

El detalle relevante de este código es que indica que las capas del block5deben ser entrenables mediante la asignación del valor Trueal parámetro set_trainablede cada capa. Ahora, definamos igual que antes la red:

keras-tensorflow-transfer-learning definicion modelo fine tunning

Aunque el pre_trained_model tendrá más capas a entrenar como podemos ver con el método summary():

keras-tensorflow-transfer-learning summary del modelo fine tunning

Ahora ya podemos compilar y entrenar la red. Usaremos los mismos hiperparámetros (optimizador RMSProp con learning rate de 1e-4), pero es importante dejar claro, para aquellos que quieran profundizar más en el tema, que estos hiperparámetros juegan un papel fundamental. Por ejemplo, en general es una buena práctica usar un learning ratemuy pequeño para limitar la magnitud de las modificaciones que se realiza en las tres capas del block5 que está ajustando. Los learning rateque son demasiado grandes pueden dañar los pesos previos que venían de la red preentrenada ya que mantenían información importante para representar a las características. Pero esto queda fuera del alcance de este libro y dejamos al lector el profundizar más en este tema si lo desea.

Volviendo al caso de uso, ahora ya estamos en disposición de compilar y entrenar nuestra nueva red neuronal usando Fine Tuning:

keras-tensorflow-transfer-learning codigo de compilación y entrenamiento del modelo fine tunning

Igual que en los anteriores modelos, veamos gráficamente como evoluciona su entrenamiento:

keras-tensorflow-transfer-learning grafica comportamiento accuracy del modelo de fine tunning

keras-tensorflow-transfer-learning grafica comportamiento loss del modelo de fine tunning

Si nos fijamos en el eje de las Y de la primera gráfica que muestra la Accuracy (para poder observar mejor su evolución están en un rango diferente en relación a la sección anterior), ahora podemos considerar que se ha mejorado, aunque se manifiesta el Overfittingigual que en el modelo anterior con menos epochs aunque a un nivel de Accuracy es mejor.

Seguramente lo que más le llame la atención al lector son las curvas de Lossde los datos de validación, que no muestra ninguna mejora real (de hecho, se está deteriorando) mientras la Accuracy se mantiene estable. Es oportuno este resultado para aprovechar y explicar qué expresa realmente esta gráfica de la evolución de la Lossde los datos de validación. En realidad lo que se muestra es un promedio de valores de Losspuntual; pero lo que importa para la Accuracy es la distribución de los valores de pérdida, no su promedio, porque la Accuracy es el resultado de un umbral binario de la probabilidad de clase predicha por el modelo. El modelo puede seguir mejorando (acaba acertando en un marco binario indicando que es perro o gato) incluso si esto no se refleja en la pérdida promedio.

Como en los anteriores modelos, podemos evaluar el modelo con los datos de Test para confirmar la mejora observada ya en el historial de entrenamiento:

keras-tensorflow-transfer-learning codigo de test del modelo fine tunning

¿Y que tal si ahora volvemos a intentar poner a prueba el modelo con la fotografía de Wiliams(o con las fotos que desee cargar el lector)? Usando el mismo código que antes, pero consultando al modelo que hemos presentado en este apartado, ahora el resultado es el esperado:

keras-tensorflow-transfer-learning inferencia del modelo con el gato wiliams

 

A modo de resumen visual les mostramos las anteriores gráficas de Accuracy sobre un mismo eje para que se puedan comparar correctamente entre ellas:

keras-tensorflow-transfer-learning codigo para comparar el comportamiento de la accuracy de todos los modelos de este capituol

Queda explícito que cada modelo claramente mejora el anterior. También se puede observar que dado que el Fine-Tuningentrena a más parámetros que el Feature Extraction, el Overfitting aparece antes.

keras-tensorflow-transfer-learning grafica del comportamiento de la accuracy de los tres modelos de este capitulo

En la práctica, pocas veces se entrena a toda una red neuronal convolucional (ConvNet) desde cero (es decir, con inicialización de los pesos aleatoriamente), porque es relativamente difícil tener un conjunto de datos de tamaño suficiente. En cambio, es común preentrenar un ConvNet en un conjunto de datos muy grande (por ejemplo, ImageNet, que recordemos que contiene más de un millón de imágenes con 1000 categorías), y luego usar esta ConvNet como inicio o como un extractor de características (features) fijas para la tarea de interés usando Trasfer Learningcon las técnicas que hemos visto en este capítulo.

En este capítulo hemos podido ver que con las ConvNet se pueden usar técnicas como Data Augmentation o Transfer Learning cuando tenemos pocos datos y nos encontramos con el problema de Overfitting. En realidad, como ya hemos dicho, nos hemos dejado otras técnicas en el tintero que pueden usarse para prevención de posibilidades para atacar el Overfitting como son las técnicas de regularización como Dropout[10], una de las más usadas actualmente.

Dado el carácter introductorio de este texto no tenemos previsto entrar en detalle, pero mencionar que Dropoutes una de las técnicas más usadas para ayudar a mitigar el Overfitting:se basa en ignorar ciertos conjuntos de neuronas de la red neuronal durante la fase de entrenamiento de manera aleatoria. Por «ignorar», nos referimos a que estas neuronas no se consideran durante una iteración concreta durante el proceso de forwardo backprogationque vimos en el capítulo 3. Keras nuevamente nos facilita la manera de expresar la aplicación de esta técnica, concretamente se trata simplemente de añadir una capa en la definición del modelo de nuestra red neuronal de la siguiente manera:

keras-tensorflow-transfer-learning codigo de ejemplo de capa de dropoout

donde como argumento se indica la fracción de neuronas que se verán afectadas por esta técnica.

Aquí terminamos el capítulo e invitamos al lector a mejorar los resultados aquí mostrados, modificando los hiperparámetros, cambiando la red neuronal, etc. No hay mejor manera de aprender que learn by doing, y con el código que el lector tiene a su disposición en el GitHub del libro puede realizar muchos experimentos por su cuenta.

Para acabar, resaltar que aunque en este capítulo hemos tratado el Transfer Learning como una simple técnica para mitigar el sobreajuste en los modelos de redes neuronales, en realidad se trata de una técnica que va mucho más allá en el Deep Learning. Se trata de una técnica de gran impacto porque permite la generalización del conocimiento: lo aprendido en un ámbito se puede aplicar a otro. Y esta es una aproximación que se está usando mucho hoy en dia para construir redes neuronales en el desarrollo de aplicaciones.

 

Referencias del capítulo

[1] Véase https://keras.io/preprocessing/image/ [Accedido: 18/08/2019]

[2] Véase https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/preprocessing/image [Accedido: 18/08/2019]

[3] Cada epoch puede tardar cerca de 1 minuto. En realidad esto depende de los recursos que colab asigne a nuestro programa y puede variar dependiendo de la ejecución.

[4] Véase https://keras.io/regularizers/ [Accedido: 18/08/2019]

[5] Véase https://keras.io/layers/core/#dropout [Accedido: 18/08/2019]

[6] Véase https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/applications [Accedido: 18/08/2019]

[7] Karen Simonyan and Andrew Zisserman, “Very Deep Convolutional Networks for Large-Scale Image Recog- nition,” arXiv (2014). Published as a conference paper at ICLR 2015 https://arxiv.org/abs/1409.1556

[8] Recordar que en el github del libro se encuentra todo el código detallado para ser ejecutado.

[9] Recordemos que las capas de poolingno tienen parámetros entrenables. En todo caso hiperparámetros que determinan su dimensión

[10] Véase https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/layers/Dropout [Accedido: 18/08/2019]