diciembre 8, 2018 6:00 pm

Jesús

>>> Descarga el código de este post aquí <<<

?? Read in English

Durante las últimas semanas hemos estado hablando copiosamente sobre la importancia de transfer learning. Incluso desarrollamos un motor de búsqueda inversa de imágenes apoyado sobre este concepto, así como un clasificador de imágenes de Flickr que hace uso de los parámetros pre-aprendidos por otras redes neuronales.

En este post hablaremos en mayor profundidad sobre transfer learning, así como en qué circunstancias vale la pena aplicarlo, y de qué manera.

Como de costumbre, puedes encontrar el código fuente asociado a este artículo en este enlace.

 

La Arquitectura es Difícil

Encontrar la arquitectura ideal para el problema que queremos resolver es una tarea ardua, tanto a nivel de tiempo como de esfuerzo.

El número de factores que debemos controlar, manejar y tantear es enorme. Más aún, teniendo en cuenta que cada vez que cambiamos al menos uno de ellos estamos accediendo a una combinación distinta, el problema rápidamente se sale de nuestras manos.

Añadido a esto, está el factor tiempo: Típicamente, las redes neuronales profundas se utilizan para problemas donde la cantidad de data es considerablemente grande, al menos lo suficientemente volumétricas como para que algoritmos tradicionales como decision trees o linear regression se vean sobrepasados.

Pero a medida que la data crece, también lo hace el tiempo necesario para entrenar una red. Así, necesariamente tenemos que esperar ciclos que pueden tomar desde un par de minutos hasta, incluso, semanas, para determinar si la nueva combinación de factores que intentamos produjo un mejor resultado que en la iteración previa.

Como puedes ver, no es difícil desanimarse al considerar la complejidad que conlleva diseñar una buena red neuronal.

Es por eso que transfer learning es una herramienta tan importante para nosotros, puesto que nos permite reutilizar la experticia, tiempo, recursos, paciencia, inteligencia y astucia de equipos multidisciplinarios que, en su momento, invirtieron incontables horas en experimentar con multitud de combinaciones de parámetros, hasta dar con una configuración lo suficientemente exitosa para servir como punto de arranque en proyectos pertenecientes a un sinnúmero de dominios variados.

 

La Data es Costosa y Escasa

Puede que no siempre sea el caso, pero la probabilidad de que no tengas suficientes datos para poder entrenar una red neuronal desde cero es bastante alta.

Incluso si cuentas con miles de imágenes en tu conjunto de datos, arquitecturas pre-entrenadas famosas como VGG-16, Inception o ResNet50 han sido entrenadas usando ImageNet, la cual tiene 100 millones de instancias en su haber. ¿Crees tener o siquiera poder conseguir 100 millones de imágenes relevantes para tu dominio? Probablemente no.

Ya sé, ya sé, en este momento te estás preguntando qué tan útil puede resultar una red neuronal especializada en reconocer objetos comunes cuando lo que buscas es implementar una solución para un dominio más especializado o, cuando menos, diferente.

La respuesta es sencilla: ¡Son increíblemente útiles!

La razón es que las redes neuronales sólo aprenden a detectar patrones complejos en las capas más profundas o superiores de su arquitectura. Es decir, aquellas capas que estén más cercanas a la capa de salida son las encargadas de reconocer patrones de alto nivel directamente vinculados al dominio o tema del conjunto de datos, mientras que las primeras capas se especializan en patrones básicos como líneas, puntos, curvas, formas y contornos. Es por este motivo que aunque tu conjunto de datos sea distinto, aún puedes extraer mucho valor de los parámetros de estas capas, puesto que estos patrones son comunes para virtualmente todas los objetos que hallamos en imágenes digitales.

Cuándo y Cómo Usar Transfer Learning

Concretamente, transfer learning consiste en tomar redes neuronales pre-entrenadas y adaptarlas a un nuevo y, posiblemente, conjunto de datos diferente. Esta adaptación está gobernada por dos factores clave:

  • El tamaño del nuevo conjunto de datos.
  • La similitud entre el nuevo conjunto de datos y el original que fue usado para entrenar a la red que queremos adaptar.

Con base en estos factores, podemos identificar cuatro escenarios o casos en los que nuestra estrategia de adaptación variará un poco.

Caso #1: El nuevo conjunto de datos es pequeño y similar al original usado para entrenar a la red.

La estrategia a aplicar en este caso consiste en:

  • Eliminar las últimas capas de la red neuronal.
  • Añadir una nueva capa totalmente conectada (fully-connected) con tantas neuronas como clases queramos predecir en nuestro nuevo conjunto de datos.
  • Inicializar ésta nueva capa con pesos aleatorios.
  • Congelar todos los pesos de las demás capas de la red pre-entrenada. Esto quiere decir que al re-entrenarla, estos parámetros no serán alterados.
  • Entrenar la red con la nueva data para ajustar los pesos de la nueva capa totalmente conectada.

Dado que ambos conjuntos de datos son similares, es de esperar que las últimas capas reconozcan patrones de alto nivel parecidos en las nuevas imágenes, razón por la cual decidimos congelarlas.

Caso #2: El nuevo conjunto de datos es pequeño y distinto al original usado para entrenar a la red.

Estrategia:

  • Eliminar la mayoría de las capas cercanas al principio de la red, puesto que sólo queremos conservar aquellas capaces de identificar patrones de bajo nivel.
  • Conectar las capas restantes con una nueva capa totalmente conectada.
  • Inicializar ésta nueva capa con pesos aleatorios.
  • Congelar todos los pesos de las demás capas de la red pre-entrenada. Esto quiere decir que al re-entrenarla, estos parámetros no serán alterados.
  • Entrenar la red con la nueva data para ajustar los pesos de la nueva capa totalmente conectada.

Caso #3: El nuevo conjunto de datos es grande y similar al original usado para entrenar a la red.

Ésta estrategia se conoce en inglés como fine-tuning, lo que se traduciría como afinamiento:

  • Remover la última capa totalmente conectada y conectarla con una nueva capa con tantas neuronas como clases tenga el nuevo conjunto de datos.
  • Inicializar ésta nueva capa con pesos aleatorios.
  • Inicializar el resto de la red con sus pesos originales.
  • Entrenar toda la red neuronal.

Dado que en esta ocasión tenemos suficiente data como para re-entrenar la red completa, no necesitamos congelar ningún peso. El hecho de que inicialicemos las capas que no eliminamos con sus pesos pre-aprendidos es para acelerar el proceso de entrenamiento.

Caso #4: El nuevo conjunto de datos es grande y distinto al original usado para entrenar a la red.

En este caso podemos utilizar exactamente la misma estrategia anterior. Sin embargo, aquí hay una alternativa:

  • Remover la última capa totalmente conectada y conectarla con una nueva capa con tantas neuronas como clases tenga el nuevo conjunto de datos.
  • Inicializar toda la red con pesos aleatorios.
  • Entrenar toda la red desde cero.

Aunque ambos conjuntos de datos no sean similares, vale la pena intentar primero con los pesos pre-aprendidos antes de optar por utilizar pesos aleatorios y entrenar desde cero. La mayoría de las veces la primera estrategia funciona lo suficientemente bien.

En el siguiente notebook utilizamos transfer learning para entrenar un clasificador de razas de perros. ¿Puedes adivinar cuál estrategia usamos y por qué?

Features de Cuello de Botella

En el notebook anterior te habrás percatado de que no usamos directamente las imágenes para entrenar nuestra nueva red, sino algo que llamamos bottleneck features o features cuello de botella.

De hecho, ni siquiera entrenamos una CNN, sino un MLP…

Básicamente, lo que hicimos fue aprovecharnos del hecho de que salvo la última capa que agregamos al final, el resto de la red nunca va a cambiar ni en estructura ni en parámetros durante el proceso de entrenamiento. Entonces, ¿para qué pasar cada imagen incontables veces por toda la red, cuando lo único que nos interesa es entrenar la última capa?

Lo que hicimos fue calcular el volumen resultante de cada imagen pasada por las capas inmutables de la red, y éstas las utilizamos para entrenar un simple MLP de manera más eficiente.

Otro aspecto importante es que uno de los modelos que entrenamos era un MLP con más de 3 millones de parámetros. Como logramos observar, aún cuando lo entrenamos durante 20 epochs, su desempeño fue decepcionante, mientras que el segundo modelo, un MLP en conjunción con una capa de agrupación global, logró reducir el número de parámetros a poco menos de 70 mil, alcanzó un accuracy del 50% en las mismas 20 epochs.

En el siguiente notebook puedes encontrar más detalles sobre cómo calcular bottleneck features.


Esto es todo por hoy.

¡Nos vemos!

>>> Descarga el código de este post aquí <<<

Sobre el Autor

Jesús Martínez es el creador de DataSmarts, un lugar para los apasionados por computer vision y machine learning. Cuando no se encuentra bloggeando, jugando con algún algoritmo o trabajando en un proyecto (muy) cool, disfruta escuchar a The Beatles, leer o viajar por carretera.

Paso 2/2: Celebra tu NUEVO EMPLEO en Machine Learning ?

A %d blogueros les gusta esto: