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”




sábado, 3 de abril de 2021

AWS in a nutshell 13: Seguridad de red y recuperación de desastres

Consiste en proteger los recursos de AWS, incluido el control del tráfico y la planificación de recuperación ante desastres.

Se  trata de planificar y configurar tanto la ACL de la red como una estrategia de grupo de seguridad. Estrategias de recuperación ante desastres que incluyen RTO, estudios piloto, 

copias de seguridad y reservas en caliente.

Crear, recrear y copiar una instantánea de volumen de EBS e implementar medidas de protección para las redes y aplicaciones web de AWS. 

Recomendaciones para el rendimiento y la seguridad de asesores de confianza,  e implementar soluciones de detección de amenazas mediante el servicio de guardia de Amazon.

13.1 Red  de ACL

ACL significa Lista de control de acceso. En Amazon Web Services, una ACL de red se aplica a subredes dentro de una VPC. estas ACL de red controlan el flujo de tráfico de red dentro y fuera de la subred. 

Es diferente a un grupo de seguridad que solo tiene reglas permitidas. También podemos configurar números de prioridad para poder controlar el orden en que se verifican las reglas de ACL de la red. Después de que haya una coincidencia con el tráfico entrante o saliente, se permite o se deniega y se detiene el procesamiento de reglas.

Red  de ACL AWS

13.2 Grupos de seguridad

Cuando planificamos cómo controlar el flujo de tráfico de red entrante y saliente, tenemos dos opciones en AWS. Una son las ACL de red, y la otra son los grupos de seguridad, 

Los grupos de seguridad usan reglas de ACL para permitir el tráfico, y ese tráfico se aplica a las instancias de EC2. Si tenemos tanto ACL de red como grupos de seguridad, primero se verifican las ACL de red. Los grupos de seguridad son aplicables a instancias específicas de EC2, no en un sentido más amplio a una subred completa como lo es una ACL de red.

13.3
Configuración de una red ACL

Tecleamos VPC en la consola principal de AWS
Tenemos este menú de opciones

Configuración de una red ACL AWS

Configuración de una red ACL Amazon Web Services



13.4 Configuración de Seguridad de Grupo

En Amazon Web Services, un grupo de seguridad es esencialmente un tipo de solución de firewall basada en la nube de software, aunque solo admite reglas de permisos para permitir ciertos tipos de tráfico a una instancia específica de EC2 o fuera de ella.
No admite reglas de denegación como las ACL de red, pero las ACL de red son diferentes porque están asociadas a subredes, no a instancias específicas de EC2. 
Para configurarlo ponemos VPC en la consola y pulsamos en Security Groups

13.5 Estrategias de recuperación de desastres

La planificación de estrategias de recuperación ante desastres es una parte importante de la planificación de la continuidad del negocio. Esto también incluye asegurarse de que los servicios de AWS que puedan ser críticos para la misión estén altamente disponibles en caso de algún tipo de desastre. Hay varios tipos diferentes de estrategias de recuperación de desastres disponibles a través de Amazon Web Services.
El propósito de la RTO  es minimizar la cantidad de tiempo que se tarda en volver a poner en funcionamiento un sistema o proceso comercial fallido a un estado funcional. 
Un RTO de dos horas, significa que es la tolerancia máxima para la cantidad de datos que se pueden perder. Esto significa implementar procesos que realizan copias de seguridad al menos una vez cada dos horas.
El acuerdo de nivel de servicio, o SLA, planifica la recuperación ante desastres de todos y cada uno de los servicios de AWS, como las instancias S3, EC2, Amazon Kinesis, bases de datos RDS, todos tienen sus propios SLA únicos. 

CloudEndure  se puede usar como herramienta de migración o, en este caso, como una herramienta de recuperación ante desastres. CloudEndure, permite retroceder a un punto en el tiempo usando una instantánea que se tomó antes de que ocurriera el problema.

CloudEndure AWS

Un proveedor de la nube como un sitio alternativo de recuperación ante desastres, podemos referirnos a esto como recuperación ante desastres como servicio o DRaaS. 
Podemos usar AWS como un sitio alternativo de recuperación ante desastres.
Debemos asegurarnos de configurar los servicios en AWS que pueden funcionar cuando cosas como los sistemas locales pueden fallar. También podemos habilitar la replicación de datos en regiones alternativas. 



13.6 Asesor de Confianza

En AWS, el asesor de confianza es una forma centralizada de determinar la postura de seguridad de su sistema ecológico AWS.
Para entrar Tecleamos Trusted Advisor en la consola AWS

Asesor de Confianza Amazon Web Services

13.7 Amazon GuardDuty 

Es importante tener un método centralizado y automatizado para detectar anomalías en nuestro entorno. Es un servicio de detección de amenazas que monitorea continuamente para detectar actividades maliciosas y comportamientos no autorizados con el fin de proteger nuestros datos, cargas de trabajo y cuentas de AWS almacenados en Amazon S3.

Tecleamos GuardDuty en la consola de AWS


Amazon GuardDuty AWS


sábado, 27 de marzo de 2021

Autoencoders apilados II: Preentrenamiento no supervisado

Si estamos abordando un problema complejo sobre una tarea supervisada pero no disponemos de etiquetas para entrenar con los datos, una solución es encontrar una red neuronal que ejecute tareas similares y reutilizar sus capas inferiores. Esto hace posible entrenar modelos complejos utilizando pocos datos de entrenamiento aunque nuestra red neuronal no haya aprendido todas las características de bajo nivel; para ello utilizaremos los detectores de características aprendidos por una red existente.

De modo análogo, si tenemos en dataset muy grande pero la mayoría no está etiquetado, podemos entrenar un autoencoder apilado utilizando todos los datos y luego reutilizar las capas más bajas entrenadas para crear una red neuronal para nuestra tarea definitiva utilizando estos datos etiquetados. Esto se muestra en la figura inferior, donde pre-entrenamos un autoencoder apilado con datos no etiquetados  y luego congelamos las capas inferiores que ya están pre-entrenadas y las utilizamos como capas inferiores de la nueva red neuronal.

 

Autoencoders apilados II: Preentrenamiento no supervisado

Es común tener muchos datos de los cuales sólo unos pocos etiquetados, construir un gran dataset no etiquetado es tan sencillo como descargar millones de imágenes de internet, pero etiquetar dichas imágenes correctamente, es una tarea que sólo los humanos podemos hacer de forma fiable. Etiquetar imágenes consume mucho tiempo y es costoso, con lo que es habitual tener sólo unos pocos miles de imágenes etiquetadas por humanos.

Utilizamos todo el dataset, tanto las imágenes etiquetadas como las que no lo están para entrenar nuestro autoencoder y reutilizamos las capas inferiores del autoencoder en nuestra nueva red neuronal.

Vamos a ver algunas técnicas para entrenar de este modo autoencoders.

Atando los pesos

Cuando un autoencoder es exactamente simétrico una técnica común consiste en atar los pesos de las capas del decodificador a los pesos de las capas del codificador. Esto reduce a la mitad el número de pesos en el modelo, acelerando el entrenamiento y limitando el riesgo de sobreentrenamiento. Si el autoencoder tiene N capas (sin contar la capa de entrada), y WL representa la conexión de los pesos a la capa L-ésima. Es decir la capa 1 es la primera capa oculta N/2 es la capa de codificación  (coding) y la capa N es la capa de salida, entonces las capas del decodificador definen sus pesos como WN-L+1 = WLT  (con L= 1,2,…..,N/2)

Los pesos atados entre capas utilizando keras son definidos por la capa personalizada.

Es común vincular los pesos del codificador y el decodificador, simplemente usando la transposición de los pesos del codificador como pesos del decodificador. Para esto, necesitamos usar una capa personalizada.

class DenseTranspose(keras.layers.Layer):

    def __init__(self, dense, activation=None, **kwargs):

        self.dense = dense

        self.activation = keras.activations.get(activation)

        super().__init__(**kwargs)

    def build(self, batch_input_shape):

        self.biases = self.add_weight(name="bias",

                                      shape=[self.dense.input_shape[-1]],

                                      initializer="zeros")

        super().build(batch_input_shape)

    def call(self, inputs):

        z = tf.matmul(inputs, self.dense.weights[0], transpose_b=True)

        return self.activation(z + self.biases)

Esta capa personalizada actúa como una capa regular densa, pero utiliza los pesos de otra capa regular densa, trasponiendo ( poner transpose_b = True es equivalente a transponer el segundo argumento, pero es más eficiente que esto ejecutar la trasposición sobre la marcha dentro de la operación matmul) Sin embargo esto utiliza su propio vector de sesgo (bias). Lo siguiente es construir un nuevo autoencoder apilado, similar al anterior pero con las capas densas del decodificador atadas a las capas densas del codificador.

keras.backend.clear_session()

tf.random.set_seed(42)

np.random.seed(42)

 

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

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

 

tied_encoder = keras.models.Sequential([

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

    dense_1,

    dense_2

])

 

tied_decoder = keras.models.Sequential([

    DenseTranspose(dense_2, activation="selu"),

    DenseTranspose(dense_1, activation="sigmoid"),

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

])

 

tied_ae = keras.models.Sequential([tied_encoder, tied_decoder])

 

tied_ae.compile(loss="binary_crossentropy",

                optimizer=keras.optimizers.SGD(lr=1.5), metrics=[rounded_accuracy])

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

                      validation_data=(X_valid, X_valid))

Este modelo tiene una ejecución de reconstrucción ligeramente inferior al anterior pero con la mitad de parámetros.

show_reconstructions(tied_ae)

plt.show()

Preentrenamiento no supervisado

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”