sábado, 10 de abril de 2021

Autoencoders III. Autoencoders convolucionales, recurrentes y con ruido

 Autoencoders convolucionales

Si estamos trabajando con imágenes, los autoencoders no funcionarán muy bien a menos que las imágenes sean muy pequeñas. De modo que si queremos construir un autoencoder para imágenes, ya sea para reducir su dimensionalidad o hacer un pre-entrenamiento no supervisado, necesitaremos construir un autoencoder convolucional. En el cual, el codificador es una red neuronal convolucional compuesta de capas convolucionales y capas de agrupación. Esto típicamente reduce la dimensionalidad espacial de las entradas (ancho y alto) mientras que incrementa su profundidad (el número de mapas de características. El decodificador debe revertirlo, agrandando la escala de la imagen y reduciendo la profundidad hasta las dimensiones originales de la imagen. Para esto podemos utilizar capas convolucionales traspuestas. Alternativamente podemos combinar capas de muestreo con capas convolucionales. 

Aquí tenemos la implementación de  un autoencoder convolucional para el dataset de moda MNIST.

En este caso el Autoencoder apilado tiene 3 capas ocultas y una capa de salida (es decir, 2 Autoencoders apilados).

tf.random.set_seed(42)

np.random.seed(42)

 

conv_encoder = keras.models.Sequential([

    keras.layers.Reshape([28, 28, 1], input_shape=[28, 28]),

    keras.layers.Conv2D(16, kernel_size=3, padding="SAME", activation="selu"),

    keras.layers.MaxPool2D(pool_size=2),

    keras.layers.Conv2D(32, kernel_size=3, padding="SAME", activation="selu"),

    keras.layers.MaxPool2D(pool_size=2),

    keras.layers.Conv2D(64, kernel_size=3, padding="SAME", activation="selu"),

    keras.layers.MaxPool2D(pool_size=2)

])

conv_decoder = keras.models.Sequential([

    keras.layers.Conv2DTranspose(32, kernel_size=3, strides=2, padding="VALID", activation="selu",

                                 input_shape=[3, 3, 64]),

    keras.layers.Conv2DTranspose(16, kernel_size=3, strides=2, padding="SAME", activation="selu"),

    keras.layers.Conv2DTranspose(1, kernel_size=3, strides=2, padding="SAME", activation="sigmoid"),

    keras.layers.Reshape([28, 28])

])

conv_ae = keras.models.Sequential([conv_encoder, conv_decoder])

 

conv_ae.compile(loss="binary_crossentropy", optimizer=keras.optimizers.SGD(lr=1.0),

                metrics=[rounded_accuracy])

history = conv_ae.fit(X_train, X_train, epochs=5,

                      validation_data=(X_valid, X_valid))

Podemos ver un pequeño esquema de nuestra red neuronal poniendo 

conv_encoder.summary()

conv_decoder.summary()

Y mostrar las reconstrucciones con 

show_reconstructions(conv_ae)

plt.show()

Autoencoders convolucionales


Autoencoders Recurrentes

Si queremos construir un autoencoder para secuencias , tal como una serie de tiempo o texto, ya sea para reducir la dimensionalidad o para aprendizaje no supervisado construiremos un autoencoder recurrente es sencillo: el codificador es típicamente una red recurrente secuencia-a-vector RNN la cual comprime la secuencia de entrada en un vector sencillo. El decodificador es una RNN  vector-a-secuencia que hace el proceso inverso.

recurrent_encoder = keras.models.Sequential([

    keras.layers.LSTM(100, return_sequences=True, input_shape=[28, 28]),

    keras.layers.LSTM(30)

])

recurrent_decoder = keras.models.Sequential([

    keras.layers.RepeatVector(28, input_shape=[30]),

    keras.layers.LSTM(100, return_sequences=True),

    keras.layers.TimeDistributed(keras.layers.Dense(28, activation="sigmoid"))

])

recurrent_ae = keras.models.Sequential([recurrent_encoder, recurrent_decoder])

recurrent_ae.compile(loss="binary_crossentropy", optimizer=keras.optimizers.SGD(0.1),

                     metrics=[rounded_accuracy])

Este autoencoder recurrente puede procesar secuencias de cualquier longitud, con 28 dimensiones en cada paso de tiempo. Esto significa que puede procesar imágenes del dataset de moda MNIST tratando cada imagen como una secuencia de filas: cada paso de tiempo la red RNN procesa una fila simple de 28 pixels. Obviamente podríamos utilizar un autoencoder recurrente para cualquier tipo de secuencia. Hemos utilizado una capa RepeatVector como primera capa para el decodificador, para asegurarnos de que su vector de  entrada alimenta el decodificador en cada paso de tiempo.

show_reconstructions(recurrent_ae)

plt.show()

Autoencoders con ruido

Otra vía para forzar a un autoencoder a aprender caracteríaticas útiles, es añadir ruido a sus entradas y tratar de recuperar las entradas iniciales libres de ruido.

El ruido puede ser un ruido puro Gaussiano añadido a su entrada o puede ser un apagado aleatorio en las entradas. 

 

Autoencoders con ruido

La implementación es sencilla, es un autoencoder apilado regular con una capa adicional de Dropout (Abandono) aplicada en la entrada del codificador. También podemos podemos utilizar una capa GausianNoise en su lugar. Recuerda que la capa Dropout solo está activa durante el entrenamiento, lo mismo para el ruido Gaussiano.

tf.random.set_seed(42)

np.random.seed(42)

 

denoising_encoder = keras.models.Sequential([

    keras.layers.Flatten(input_shape=[28, 28]),

    keras.layers.GaussianNoise(0.2),

    keras.layers.Dense(100, activation="selu"),

    keras.layers.Dense(30, activation="selu")

])

denoising_decoder = keras.models.Sequential([

    keras.layers.Dense(100, activation="selu", input_shape=[30]),

    keras.layers.Dense(28 * 28, activation="sigmoid"),

    keras.layers.Reshape([28, 28])

])

denoising_ae = keras.models.Sequential([denoising_encoder, denoising_decoder])

denoising_ae.compile(loss="binary_crossentropy", optimizer=keras.optimizers.SGD(lr=1.0),

                     metrics=[rounded_accuracy])

history = denoising_ae.fit(X_train, X_train, epochs=10,

                           validation_data=(X_valid, X_valid))

Podemos ver las reconstrucciones aqui:

tf.random.set_seed(42)

np.random.seed(42)

 

noise = keras.layers.GaussianNoise(0.2)

show_reconstructions(denoising_ae, noise(X_valid, training=True))

plt.show()

Autoencoders con ruido

En la imagen se ven las imágenes de entrada con ruido y su reconstrucción sin ruido. Nótese cómo el autoencoder genera detalles que no están en la entrada, como por ejemplo el cuello del jersey blanco.


Traducido del capítulo 17 de “Hands-On Machine Learning with Scikit-Learn, Keras and Tensorflow, 2nd Edition by Aurelien Géron (O’Reilly). Copyright 2019 Kiwisoft S.A.S., 978-1-492-03264-9”




No hay comentarios:

Publicar un comentario