Introduction to Deep Learning

Introducción al autoencoder

Autor:Nathan Hubens

Linkedind: https://www.linkedin.com/in/nathan-hubens

Tradutor: Paula Vidal

 

 

Los autoencoders son redes neuronales con el objetivo de generar nuevos datos primero comprimiendo la entrada en un espacio de variables latentes y luego reconstruyendo la salida en base a la información adquirida. Este tipo de red consta de dos partes:

  1. Encoder: la parte de la red que comprime la entrada en un espacio de variables latentes y que puede representarse mediante la función de codificación h = f (x).
  2. Decoder: la parte que trata de reconstruir la entrada en base a la información recolectada previamente. Se representa mediante la función de decodificación r = g (h).

1 3

Arquitectura de un autoencoder.

 

El autoencoder se puede describir con la siguiente función d (f (x)) = r  donde r es similar a la entrada original de x.

¿Por qué copiar la entrada en la salida?

Lo que esperamos es que, cuando entrenamos un autoencoder y copiamos la entrada, el espacio de variables latentes h pueda tomar características útiles para nosotros.

Esto se puede lograr imponiendo límites a la acción de codificación, forzando el espacio h que sea de menores  dimensiones que x. En este caso, el autoencoder viene llamado undercomplete. Al entrenar el espacio undercomplete, traemos el autoencoder que capturar las características más relevantes de los datos de entrenamiento. Si no les damos suficientes restricciones, la red se limita a la tarea de copiar la entrada en la salida, sin individuar ninguna información útil sobre la distribución de datos. Esto puede suceder incluso cuando el tamaño del subespacio latente tiene el mismo tamaño que el espacio inicial; en el caso cuando tenemos un caso de autoencoder overcomplete, significa que  el tamaño del espacio de variables latentes es mayor que las entradas. En estos casos, incluso con  simples encoder y decoder lineales, podemos copiar la entrada en la salida sin aprender nada sobre los datos.

Idealmente, es posible entrenar con éxito cualquier arquitectura basada en el autoencoder eligiendo adecuadamente los parámetros y la capacidad de cada encoder-decoder en función de la complejidad de los datos a modelar.

 

El uso de los autoencoder

Hasta la fecha, la reducción de ruido y la reducción de dimensionalidad para la visualización de datos se consideran las aplicaciones más interesantes de autoencoders. Con el ajuste apropiado de

 

Con la configuración apropiada de la dimensionalidad y las restricciones relacionadas en la dispersión de los datos, a través del autoencoder es posible obtener proyecciones en subespacios de mayor interés en comparación con métodos lineales como PCA.

Los autoencoders se entrenan automáticamente a través de datos de muestra. Esto significa que es fácil entrenar la red para tener un buen rendimiento en tipos similares de entrada, sin la necesidad de generalizar. Es decir, solo la compresión realizada en datos similares a los utilizados en el conjunto de entrenamiento tendrá buenos resultados, pero si se realiza en diferentes datos no será muy efectiva. Otras técnicas de compresión como JPEG serán más capaces de realizar esta función.

 

Estas redes neuronales están capacitadas para conservar la mayor cantidad de información posible cuando se insertan en el encoder y luego en el decoder, pero también para que las nuevas representaciones adquieran diferentes tipos de propiedades. Se describen cuatro tipos de autoencoders , es por esto crearemos un ejemplo para cada uno de ellos utilizandoòps en framework Keras y en el dataset MNIST.

 

Tipos de autoencoder

En este artículo, enumeramos cuatro:

  1. Vanilla autoencoder
  2. Autoencoder multicapa
  3. Autoencoder convolucional
  4. Autoencoder regularizado

Vanila autoencoder

Es la forma más simple, caracterizada por una red de tres capas, es decir, una red neuronal con una sola capa oculta. La entrada y la salida son las mismas y, en nuestro caso, aprendemos cómo reconstruir la entrada mediante el uso del optimizador Adam , como función de pérdida, la desviación mínima del cuadrado.

En esta tipología estamos en el caso de encoder undercomplete donde la capa oculta, con un tamaño igual a 64, es más pequeña que la de la entrada (784), obtenida de la siguiente fórmula 28x28x1. Esta restricción fuerza a la red neuronal a aprender de una representación de datos comprimida.

 

input_size = 784
hidden_size = 64
output_size = 784

x = Input(shape=(input_size,))

# Encoder
h = Dense(hidden_size, activation='relu')(x)

# Decoder
r = Dense(output_size, activation='sigmoid')(h)

autoencoder = Model(input=x, output=r)
autoencoder.compile(optimizer='adam', loss='mse')

 

Autoencoder multicapa

Si solo una capa oculta no es suficiente, podemos extender el autoencoder a lo largo de la dimensión de profundidad. Nuestra implementación ahora usa tres capas ocultas para una mejor generalización, pero también tendremos que hacer que la red sea simétrica utilizando la capa intermedia.

input_size = 784
hidden_size = 128
code_size = 64

x = Input(shape=(input_size,))

# Encoder
hidden_1 = Dense(hidden_size, activation='relu')(x)
h = Dense(code_size, activation='relu')(hidden_1)

# Decoder
hidden_2 = Dense(hidden_size, activation='relu')(h)
r = Dense(input_size, activation='sigmoid')(hidden_2)

autoencoder = Model(input=x, output=r)
autoencoder.compile(optimizer='adam', loss='mse')

Autoencoder convolucional

Surge una pregunta: ¿podrían usarse autoencoders con convoluciones en lugar de capas conectadas por completo?

Y la respuesta es sí. El principio es el mismo, pero se usan vectores tridimensionales en lugar de vectores unidimensionales. La imagen de entrada se muestrea para obtener una representación latente, es decir, una reducción dimensional, lo que obliga al autoencoder a aprender de una versión comprimida de la imagen.

x = Input(shape=(28, 28,1)) 

# Encoder
conv1_1 = Conv2D(16, (3, 3), activation='relu', padding='same')(x)
pool1 = MaxPooling2D((2, 2), padding='same')(conv1_1)
conv1_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(pool1)
pool2 = MaxPooling2D((2, 2), padding='same')(conv1_2)
conv1_3 = Conv2D(8, (3, 3), activation='relu', padding='same')(pool2)
h = MaxPooling2D((2, 2), padding='same')(conv1_3)


# Decoder
conv2_1 = Conv2D(8, (3, 3), activation='relu', padding='same')(h)
up1 = UpSampling2D((2, 2))(conv2_1)
conv2_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(up1)
up2 = UpSampling2D((2, 2))(conv2_2)
conv2_3 = Conv2D(16, (3, 3), activation='relu')(up2)
up3 = UpSampling2D((2, 2))(conv2_3)
r = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up3)

autoencoder = Model(input=x, output=r)
autoencoder.compile(optimizer='adam', loss='mse')

Autoencoder regularizado

Existen otros métodos mediante los cuales podemos restringir la reconstrucción del autoencoder como una alternativa a la imposición de una dimensionalidad reducida de las capas ocultas. En lugar de limitar la capacidad del modelo manteniendo una arquitectura poco profunda del encoder y decoder , así como una reducción forzada, los autoencoders regularizados utilizan una función de pérdida para alentar al modelo a asumir propiedades que van más allá de la simple capacidad de copiar la entrada en la salida . En la práctica, encontramos dos tipos diferentes: autoencoder disperso y Denoising autoencoder.

  1. Autoencoder escaso: generalmente se utilizan para la clasificación. Al entrenar un autoencoder, las unidades ocultas en la capa intermedia se activan con demasiada frecuencia. Para evitar esto, debemos reducir su tasa de activación limitándola a una fracción de los datos de entrenamiento. Esta restricción se denomina restricción de dispersión, porque cada unidad se activa solo mediante un tipo de entrada predefinido.
input_size = 784
hidden_size = 64
output_size = 784

x = Input(shape=(input_size,))

# Encoder
h = Dense(hidden_size, activation='relu', activity_regularizer=regularizers.l1(10e-5))(x)

# Decoder
r = Dense(output_size, activation='sigmoid')(h)

autoencoder = Model(input=x, output=r)
autoencoder.compile(optimizer='adam', loss='mse')

Otro cambio que podemos hacer durante la fase de reconstrucción es agregar un término de regularización a nuestra función de pérdida: por ejemplo, un regulador de tipo 1 introduce una penalización en la función de pérdida, que actúa durante la fase de optimización. Como resultado, tendremos menos activaciones que las de un autoencoder de Vanilla

2.Denoising autoencoder:En lugar de agregar penalización a la función de pérdida, podemos hacer que el objeto cambie, agregando ruido a la imagen de entrada y haciendo que el autoencoder aprenda a eliminarlo de manera autónoma. Esto significa que la red extraerá solo la información más relevante y aprenderá de una representación sólida de los datos

x = Input(shape=(28, 28, 1))

# Encoder
conv1_1 = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
pool1 = MaxPooling2D((2, 2), padding='same')(conv1_1)
conv1_2 = Conv2D(32, (3, 3), activation='relu', padding='same')(pool1)
h = MaxPooling2D((2, 2), padding='same')(conv1_2)


# Decoder
conv2_1 = Conv2D(32, (3, 3), activation='relu', padding='same')(h)
up1 = UpSampling2D((2, 2))(conv2_1)
conv2_2 = Conv2D(32, (3, 3), activation='relu', padding='same')(up1)
up2 = UpSampling2D((2, 2))(conv2_2)
r = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up2)

autoencoder = Model(input=x, output=r)
autoencoder.compile(optimizer='adam', loss='mse')
0 comentarios

Dejar un comentario

¿Quieres unirte a la conversación?
Siéntete libre de contribuir

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *