enero 12, 2019 6:00 pm

Jesús

?? Read in English

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

En el mundo de deep learning, más usualmente significa mejor. Más features, más capas, mayor profundidad, más parámetros, más data, más imágenes, más GPU, más recursos, más, más, más. Y es que el aspecto diferenciador de las redes neuronales profundas es su potencial de representar cualquier función, por compleja que sea, simplemente añadiendo más capas.

Entonces, sin importar el problema que tengamos en frente, podemos construir una red neuronal invencible en dicho dominio, ¿verdad? Sí… En teoría.

Alguien alguna vez dijo que no hay teoría alguna que sobreviva el primer contacto con la realidad. Pocas palabras más sabias que éstas se han pronunciado jamás.

El Problema del Gradiente Fantasma

Ha sido un día largo de trabajo. Han pasado horas desde que diseñaste tu primera arquitectura. A pesar de que la primera red que se te ocurrió tenía sólo un par de capas, los resultados eran prometedores. Después de jugar un poco con los hiperparámetros, decides que es hora de profundizar, por lo que agregas un par de capas más a tu red. Tu métrica elegida reporta una mejora del 20%… ¡Excelente!

Tu entusiasmo te lleva a añadir más y más capas, y aunque el entrenamiento toma más tiempo (lo cual tiene sentido, puesto que mayor profundidad implica más parámetros), las mejoras no dejan de llegar. Eso sí, no son tan cuantiosas como antes.

Convencido de que tu iteración más reciente superará el desempeño de la anterior, decides tomarte un break. A tu vuelta, observas con horror y confusión como ésta nueva red neuronal no sólo no mejoró a su predecesora, sino que lo hace peor… Mucho peor.

¿Qué clase de brujería es esta?

Esta circunstancia suele producirse a causa de lo que en la comunidad se denomina El Problema del Gradiente Fantasma o, en inglés, The Vanishing Gradient Problem.

En toda red neuronal, la derivada o gradiente del error cometido en cada instancia de entrenamiento debe ser transmitido de las últimas a las primeras capas, mediante un proceso conocido como backpropagation. En pocas palabras, así es como las redes neuronales aprenden de sus equivocaciones.

Sin embargo, cuando dichas redes son muy profundas, la proporción del error que se transmite de una capa a otra es incrementalmente menor, lo que hace que el entrenamiento tome una cantidad absurda de tiempo y, en algunas instancias, el gradiente se desvanece por completo (se vuelve 0), lo que significa que a partir de ese punto, la red no aprenderá nada.

Redes Residuales (ResNets)

Una manera de combatir esto es saltar conexiones entre capas. En la mayoría de las redes neuronales, cada capa está conectada a la siguiente. Eso también es cierto en el caso de las redes residuales. Sin embargo, su gran ventaja es que cuentan con caminos alternos en los que una capa está conectada a otra, dos, tres, cuatro o N capas de distancia, lo que, en efecto, hace que el gradiente no tenga que viajar tanto durante backpropagation, combatiendo así, el Problema del Gradiente Fantasma.

El tipo de conexiones descritas en el párrafo anterior se conocen como conexiones atajo o, en inglés, skip connections y es gracias a ella que podemos construir redes gigantescas, de hasta 1000 capas, sin que se degrade su desempeño (de hecho, mejora, como dicta la teoría).

El Bloque Identidad

Como su nombre lo indica, es un subconjunto de capas de las ResNets en las que, aparte de aprender la función correspondiente al dominio del problema (llamémosla f(x)), la red también se centra en aprender la función identidad (llamémosla I(x) = x), combinando ambos resultados mediante una suma. La imagen de abajo describe mejor esta situación.

Podemos ver que el camino principal realiza las operaciones tradicionales de una CNN, (es decir, aproximar f(x)), mientras que el camino de arriba, el atajo, se centra en producir una salida idéntica a la entrada (I(x)). Este bloque se usa cuando la entrada y la salida tienen las mismas dimensiones.

El Bloque Convolucional

Éste es el segundo tipo de bloque en el que se apoyan las ResNets. Es el que debemos utilizar cuando las dimensiones de la entrada y la salida no coinciden (por tanto, no podemos modelar la función identidad adecuadamente).

En la imagen observamos que en un bloque convolucional utilizamos, claramente una capa convolucional. No obstante, a diferencia de su función tradicional en las CNNs, está capa convolucional no tiene como meta detectar características específicas, sino reducir la dimensionalidad del volumen de entrada.

Al igual que sucede con el bloque identidad, los resultados de ambos caminos son combinados mediante una adición.

Estos dos bloques son el ingrediente mágico de las ResNets. Para una explicación en mayor profundidad, te animo a que veas el siguiente video (en inglés):

Manos a la Obra

En el siguiente notebook construiremos los bloques identidad y convolucionales para implementar una ResNet50 (es decir, una ResNet con 50 capas).

La mayoría de las veces no tendremos que implementar una ResNet de cero, puesto que los frameworks más populares como Keras, PyTorch y TensorFlow vienen con una versión pre-entrenada de ResNet50, pero es una buena manera de consolidar lo que hemos aprendido en este artículo.

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

Nos vemos.

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.