Técnicas de Regularización Básicas para Redes Neuronales

Source: Deep Learning on Medium

La siguiente historia le sonará familiar a más de un@. Imaginemos por un momento que tenemos que resolver un problema de datos usando un algoritmo de Machine Learning clásico. Una estrategia muy socorrida sería acotar primero el número de variables de entrada, con el fin de reducir la dimensionalidad del problema, y de esa forma mejorar el rendimiento y el tiempo de entrenamiento del modelo.

En la actualidad cuando usamos Deep Learning la laboriosa tarea de optimizar nuestros procesos ha quedado un poco en segundo plano, gracias sobre todo a la llegada de las GPU y el fácil acceso a ellas. Como contamos con más recursos ya no estamos dispuestos a seguir sacrificando ningún detalle de los datos de entrada, así que introducimos a la red absolutamente todas las variables, por muchas que sean. Además nos empeñamos en minimizar el error hasta el extremo, lo que se traduce en un aumento sin control del número de capas y parámetros de nuestra red, animados siempre por el Teorema de Aproximación Universal.

Este engordamiento hace que la complejidad de la red sea mayor, pero también que el riesgo de sobreajuste se dispare, sobre todo cuando tenemos pocas muestras de entrenamiento (el número de muestras de entrada sería mucho menor que el número de parámetros usados por la red para ajustarse a esos escasos datos). Para acabar con este problema es precisamente para lo que se utilizan las conocidas como técnicas de regularización.

A continuación haremos un breve repaso de las más usadas a día de hoy, debido en gran parte a su buen funcionamiento.

Regularización L2

La idea detrás de este tipo de regularización es reducir el valor de los parámetros para que sean pequeños.

Esta técnica introduce un término adicional de penalización en la función de coste original (L), añadiendo a su valor la suma de los cuadrados de los parámetros (ω).

La mala noticia es que este nuevo término puede ser alto; tanto que la red minimizaría la función de coste haciendo los parámetros muy cercanos a 0, lo que no sería nada conveniente. Es por ello que multiplicaremos ese sumando por una constante (λ) pequeña, cuyo valor escogeremos de forma arbitraria (0.1, 0.01, …).

La función de coste queda por tanto así:

Y la actualización de los pesos en cada iteración del descenso del gradiente seguiría la siguiente fórmula:

Si necesitáramos aplicar más regularización simplemente bastaría con aumentar el valor de λ.

Esta es la regularización que se aplica en la regresión conocida como Ridge.

Regularización L1

Existe otra técnica muy parecida a la anterior denominada regularización L1 donde los parámetros en el sumatorio del término de penalización no se elevan al cuadrado, sino que se usa su valor absoluto.

Esta variante empuja el valor de los parámetros hacia valores más pequeños, haciendo incluso que la influencia de algunas variables de entrada sea nula en la salida de la red, lo que supone una selección de variables automática. El resultado es una una mejor generalización, pero sólo hasta cierto punto (la elección del valor de λ cobra más importancia en este caso).

Es la regularización que aplica la regresión Lasso.

Decaimiento de los pesos (Weight decay)

Esta técnica podríamos decir que es idéntica a la regularización L2, pero aplicada en otro punto. En lugar de introducir la penalización como un sumando en la función de coste, la añadimos como un término extra en la fórmula de actualización de los pesos:

Como vemos esta actualización es prácticamente igual a la actualización de los pesos en la regularización L2, salvo que en este caso no aparece un 2 multiplicando en el término añadido.

Dropout

Esta técnica difiere de las vistas hasta el momento. El procedimiento es sencillo: por cada nueva entrada a la red en fase de entrenamiento, se desactivará aleatoriamente un porcentaje de las neuronas en cada capa oculta, acorde a una probabilidad de descarte previamente definida. Dicha probabilidad puede ser igual para toda la red, o distinta en cada capa.

[paper]

Lo que se consigue con esto es que ninguna neurona memorice parte de la entrada; que es precisamente lo que sucede cuando tenemos sobreajuste.

Una vez tengamos el modelo listo para realizar predicciones sobre muestras nuevas, debemos compensar de alguna manera el hecho de que no todas las neuronas permanecieran activas en entrenamiento, ya que en inferencia sí que estarán todas funcionando y por tanto habrá más activaciones contribuyendo a la salida de la red. Un ejemplo de dicha compensación podría ser multiplicar todos los parámetros por la probabilidad de no descarte.

Normalización por lotes (Batch normalization)

La historia de esta técnica es curiosa. Se presentó como una solución para reducir algo llamado Internal Covariate Shift, pero parece que no es eso lo que hace. Aún así es una técnica esencial para redes neuronales por todo lo que aporta, como explicamos a continuación.

La normalización en lotes consiste básicamente en añadir un paso extra, habitualmente entre las neuronas y la función de activación, con la idea de normalizar las activaciones de salida. Lo ideal es que la normalización se hiciera usando la media y la varianza de todo el conjunto de entrenamiento, pero si estamos aplicando el descenso del gradiente estocástico para entrenar la red, se usará la media y la varianza de cada mini-lote de entrada.

Nota: cada salida de cada neurona se normalizará de forma independiente, lo que quiere decir que en cada iteración se calculará la media y la varianza de cada salida para el mini-lote en curso.

A continuación de la normalización se añaden 2 parámetros: un bias como sumando, y otra constante similar a un bias pero que aparece multiplicando cada activación. Esto se hace para que el rango de la entrada escale fácilmente hasta el rango de salida, lo que ayudará mucho a nuestra red a la hora de ajustar a los datos de entrada, y reducirá las oscilaciones de la función de coste. Como consecuencia de esto podremos aumentar la tasa de aprendizaje (no hay tanto riesgo de acabar en un mínimo local) y la convergencia hacia el mínimo global se producirá más rápidamente.

[source]

La normalización por lotes es más una técnica de ayuda al entrenamiento que una estrategia de regularización en sí misma. Esto último se logra realmente aplicando algo adicional conocido como momentum. La idea de este momentum es que cuando introduzcamos un nuevo mini-batch de entrada (N muestras procesadas en paralelo) no se usen una media y una desviación muy distintas a las de la iteración anterior, para lo que se tendrá en cuenta el histórico, y se elegirá una constante que pondere la importancia de los valores del mini-batch actual frente a los valores del anterior. Gracias a todo esto se conseguirá reducir el sobreajuste.

Aumento de los datos (Data augmentation)

La idea es aplicar diversas transformaciones sobre las entradas originales, obteniendo muestras ligeramente diferentes pero iguales en esencia, lo que permite a la red desenvolverse mejor en la fase de inferencia.

Esta técnica se utiliza mucho en el campo de la visión artificial porque funciona de maravilla (en otros campos está por explorar). Dentro de dicho contexto, una misma imagen de entrada será procesada por la red neuronal tantas veces como epochs ejecutemos en entrenamiento; provocando que la red acabe memorizando la imagen si estamos entrenamos demasiado. Lo que haremos es aplicar transformaciones de forma aleatoria cada vez que volvamos a introducir la imagen a la red.

Ejemplos de transformaciones son:

  • Voltear la imagen en horizontal / vertical
  • Rotar la imagen X grados.
  • Recortar, añadir relleno, redimensionar, …
  • Aplicar deformaciones de perspectiva
  • Ajustar brillo, contraste, saturación, …
  • Introducir ruido, defectos, …
  • Combinaciones de las anteriores 🙂
Ejemplo usando fastai

De esta forma contaremos con más información para entrenamiento sin necesidad de obtener muestras adicionales, y también sin alargar los tiempos. Lo mejor es que si por ejemplo nuestra red se dedica a clasificar imágenes o detectar objetos, esta técnica conseguirá que el modelo sea capaz de obtener buenos resultados para imágenes tomadas desde distintos ángulos o bajo distintas condiciones de luz. Por tanto conseguiremos que la red no sobreajuste y que generalice mejor.

Parada temprana (Early Stopping)

Y por último una técnica que trata de aplicar ciertas reglas para saber cuándo es momento de parar el entrenamiento, de forma que no se produzca sobreajuste a los datos de entrada, ni tampoco subajuste.

La regla más extendida sería la de entrenar el modelo monitorizando su rendimiento y guardando sus parámetros al finalizar cada epoch, hasta que apreciemos que el error de validación aumenta de forma sostenida (hay empeoramientos que son debidos a la componente estocástica del algoritmo). Nos quedaremos con el modelo que teníamos justo en el momento anterior.

Ejemplo de entrenamiento con fastai

Cabe recordar en este punto la importancia de elegir un buen conjunto de validación 🙂