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”



sábado, 20 de marzo de 2021

AWS in a nutshell 12. IAM Identity and Access Management

 12.1 Políticas IAM

Las políticas de IAM son esencialmente colecciones de permisos relacionados que podemos asignar a usuarios, grupos o roles. Los administramos  desde la consola de administración de AWS escribiendo IAM en el buscador
Podemos administrar roles y permisos para:
  -Usuarios
  -Grupos
  -Cuentas
Podemos agregar un usuario a un grupo, copiar permisos de un usuario existente o,  adjuntar políticas existentes directamente.


12.2 Roles IAM

En Amazon Web Services, se pueden usar los roles de IAM para otorgar los permisos adecuados a las entidades de software que necesitan acceder a los recursos de AWS.
Podemos determinar si la entidad de confianza es un:
- servicio de AWS.
  -EC2
- una función lambda. 
- otra cuenta de AWS,
- una identidad web
- alguna otra entidad de federación de identidad SAML 2.0
También podemos utilizar el editor visual o podemos hacer clic en JSON y escribirlo manualmente.


12.3 Simulador de políticas IAM

Con el tiempo, a medida que administramos más y más usuarios, grupos y roles de IAM,  encontraremos que puede ser difícil rastrear qué permisos efectivos se aplican realmente, especialmente cuando tenemos usuarios que pueden ser miembros de varios grupos, etc.
Ahí es donde entra en juego el simulador de políticas de IAM. Está disponible en esta URL,  policysim.aws.amazon.com.  
La aplicación IAM Policy Simulator incluye un panel de navegación y un panel "Policy Simulator". 
Muestra a la izquierda de forma predeterminada  mis usuarios de IAM,  Grupos  y Roles. 
Aquí podemos ver que permisos están habilitados por ejemplo, para cualquier usuario que sea miembro de un grupo. Es casi igual para los roles. Si tenemos una función específica que queremos probar, por ejemplo una función de servicio de Amazon para ECS, y queremos probar para acceder a algo, ya sea Amazon S3 o cualquier otra cosa que esté disponible en la lista, o cualquier acción, para ello pulsamos Run Simulation. 


12.4 Autentificación multifactor

La autenticación multifactor, o MFA, significa que los usuarios deben especificar factores de autenticación adicionales al iniciar sesión, más allá del nombre de usuario y contraseña tradicionales. 
Por ejemplo, exigir a un usuario que introduzca un nombre de usuario y una contraseña y luego poseer un teléfono inteligente donde se envía un código de inicio de sesión único.
La autenticación multifactorial combina dos o más categorías de autenticación.
 
Podría ser algo que conozcamos, como un nombre de usuario y una contraseña, o algo que tengamos, como una tarjeta inteligente o un dispositivo móvil que reciba algún tipo de código de autenticación.


12.5 Directorio de servicios

Un servicio de directorio de red es una base de datos de red centralizada. El tipo de elementos que encontraremos en esta base de datos puede variar desde cosas como cuentas de usuario, grupos, dispositivos; por ejemplo, máquinas unidas a un dominio de Microsoft Active Directory o configuraciones de aplicaciones y otras configuraciones. Todos estos elementos se pueden almacenar en una base de datos de red central.


12.5.1 AWS Managed Microsoft Active Directory o AD.

En realidad estamos ejecutando Microsoft Active Directory, en la nube pero está administrado. No necesitamos implementar instancias manualmente o configurar el software del controlador de dominio. 

12.5.2  simple AD. 

Es muy similar al estándar de Microsoft Active Directory, es una instancia subyacente de Linux EC2 que ejecuta Samba como un servidor compatible con Active Directory. 


12.5.2.1 Configuracion de simple AD.
Paso 1 elegir  simple AD
Paso 2 elegir 
Small  < 500 usuarios
Large  > 500
Paso 3
elegir VPC y Subnets
Paso 4
Revisar y crear
asignamos nuestra instancia al dominio.
Paso 1 Elegimos la Amazon Machine Image (AMI)
Paso 2 elegimos un tipo de instancia
Paso 3 configuramos los detalles de la instancia

12.5.3 conector AD

Es una función proxy que puede tomar cualquier solicitud de autenticación, por ejemplo, para recursos de AWS y redirigirla a nuestro Microsoft Active Directory local. 


12.5.4 Grupos de usuarios de Amazon Cognito. 
Esto es de interés para los desarrolladores para agregar el registro de cuentas de usuario y tipos de características de inicio de sesión a aplicaciones personalizadas. 


12.5.4.1 Configuración de Amazon Cognito


Amazon Cognito es un servicio para desarrolladores que permite agregar capacidades de usuario a nuestras aplicaciones. Eso incluye 
Registro de usuarios
Inicio de sesión de usuarios
Control de acceso 
Inicio de sesión de IDP de terceros
Los desarrolladores podrían crear sus aplicaciones de manera que permitiría inicios de sesión de terceros utilizando las credenciales de Google o Facebook o incluso a través de Microsoft Active Directory.
El servicio Amazon Cognito admite estándares de seguridad comunes cuando se trata de autenticación y autorización, incluido SAML 2.0; abrir autenticación 2.0; y OpenID Connect. Cognito también admite grupos de usuarios o identidades de usuario, grupos de identidades, así como proveedores de identidad externos. 

IAM Identity and Access Management (AWS)


12.6 Gestión de identidad y acceso

Identity and Access Management, o IAM, es una parte de AWS que controla el acceso a los recursos. Mediante la creación y gestión de Usuarios, y luego organizando a esos usuarios en Grupos para facilitar la gestión a mayor escala, y también la creación y gestión de Roles.

12.7 Usuarios de IAM y la GUI

En  AWS, podemos crear usuarios de IAM para permitir el acceso programático a los recursos de AWS, por ejemplo, para los desarrolladores. O podemos crear cuentas de usuario de IAM para permitir el acceso a la consola de administración, como hacemos a continuación.

Consola AWS  → IAM   → (panel izquierdo) Users → (botón ) Add User

Identity and Access Management, o IAM

También está disponible por comandos en Cli y Powershell

12.8 Política de contraseña de usuario

Las políticas de seguridad de nuestra empresa pueden tener requisitos específicos cuando se trata de inicios de sesión de usuarios en términos de cómo se crean, administran y usan las contraseñas. Entonces, tenemos la capacidad de configurar la Política de contraseñas de administración de acceso e identidad de AWS.

Consola → IAM   → (panel izquierdo) account settings → (botón) Change password Policy

12.9 Inicio de sesión de usuario de IAM

En AWS, se pueden crear usuarios de IAM para permitir el acceso de la consola de administración de AWS o mediante programación a los recursos de AWS. En la Consola de administración de IAM, vemos los usuarios, según el navegador de la izquierda. A la derecha, vemos que tenemos un usuario con el nombre de JGold, que está en un grupo llamado Group1. Entonces, si hacemos clic directamente en JGold para abrir las propiedades de la cuenta de usuario, podemos ver cosas como el nombre del recurso de Amazon,

Consola → IAM   → (panel izquierdo) Users

AWS Identity and Access Management, o IAM


12.10 Grupos de IAM y la GUI

Los grupos se pueden usar en AWS para organizar a los usuarios que tienen requisitos similares para acceder a los recursos de AWS en lugar de asignar los mismos permisos de acceso a los recursos a usuarios individuales una y otra vez. Abrimos la Consola de administración de AWS para crear un grupo de AWS IAM. Y buscamos IAM pulsamos para  para abrir la consola de administración de IAM. Aparece el panel de control, donde podemos ver muy rápidamente que tenemos cero Grupos y cero Usuarios. Entonces, lo que vamos a hacer es hacer clic en la vista Grupos a la izquierda.

Consola → IAM   → (panel izquierdo) Group → (botón ) Create New Group

También en está disponible por comandos en CLI y PowerShell


sábado, 13 de marzo de 2021

Autoencoders apilados I: Reducción de dimensionalidad

Los autoencoders, al igual que otras redes neuronales pueden tener múltiples capas ocultas. En este caso los llamamos autoencoders apilados o autoencoders profundos. Añadir más capas ayuda al autoencoder a aprender codificaciones más complejas. Pero hay que ser cuidadoso de no implementar un autoencoder más potente de lo que necesitamos. Imaginamos por ejemplo un codificador tan potente que es capaz de mapear cada número individual de forma arbitraria y un decodificar que hace el mapeo inverso. Obviamente tal autoencoder debería ser capaz de reconstruir los datos de entrenamiento perfectamente, pero no sería capaz de aprender ninguna representación útil de los datos en el proceso (y esto no es útil para generalización de nuevas instancias).

La arquitectura de un autoencoder apilado es tipicamente simétrica con respecto a la capa oculta central (la capa de codificación). Por ejemplo para codificar el dataset de moda MINST 

Debería tener 784 entradas seguidas por una capa oculta de 100 neuronas , luego una capa central de 30 neuronas y otra capa oculta de 100 neuronas, finalmente una capa de salida de 784 salidas.

 

Autoencoders apilados I: Reducción de dimensionalidad

Vamos a construir un autoencoder apilado para trabajar con el dataset MNIST, utilizaremos activación SELU.

Cargamos el dataset MNIST

(X_train_full, y_train_full), (X_test, y_test) = keras.datasets.fashion_mnist.load_data()

X_train_full = X_train_full.astype(np.float32) / 255

X_test = X_test.astype(np.float32) / 255

X_train, X_valid = X_train_full[:-5000], X_train_full[-5000:]

y_train, y_valid = y_train_full[:-5000], y_train_full[-5000:]

Construimos un Autoencoder apilado con 3 capas ocultas y 1 capa de salida (es decir, 2 Autoencoders apilados).

def rounded_accuracy(y_true, y_pred):

    return keras.metrics.binary_accuracy(tf.round(y_true), tf.round(y_pred))

tf.random.set_seed(42)

np.random.seed(42)

 

stacked_encoder = keras.models.Sequential([

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

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

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

])

stacked_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])

])

stacked_ae = keras.models.Sequential([stacked_encoder, stacked_decoder])

stacked_ae.compile(loss="binary_crossentropy",

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

history = stacked_ae.fit(X_train, X_train, epochs=20,

                         validation_data=(X_valid, X_valid))

Echemos un vistazo al código: el modelo de autoencoder se divide en dos submodelos, el codificador y el decodificador.

El codificador toma imágenes en escala de grises de 28x28 pixels, las aplana de tal forma que cada imagen es metida en un vector de 784 posiciones, entonces procesa tales vectores a través de dos capas densas de tamaños que van disminuyendo (primero a 100 unidades y después a 30), ambas capas utilizan la función de activación SELU. Para cada imagen de entrada, el codificador genera un vector de 30 posiciones.

El decodificador toma este vector de 30 posiciones (que es la salida del codificador) y lo procesa a través de dos capas densas incrementando sus tañamos desde 100 unidades hasta 784 y reconstruye el vector final como una imagen de escala de grises de 28x28 pixels con lo que la salida tiene el mismo tamaño que la entrada del codificador.

Cuando compilamos el autoencoder apilado utilizamos pérdida de entropía cruzada binaria en vez del error cuadrático medio. Estamos tratando esta  tarea de reconstrucción como un problema de clasificación binaria múltiple: cada intensidad de pixel representa la probabilidad de que el pixel sea negro. Enmarcando este problema más bien como un problema de regresión, lo que hace que el modelo tienda a converger más rápidamente.

Finalmente entrenamos el modelo utilizando X_train como entradas y como objetivos, y similarmente utilizamos X_valid como entradas de validación y como objetivos.

Visualizando las reconstrucciones

Una forma de asegurarnos de que en autoencoder es entrenado apropiadamente es comparar las entradas con las salidas. Las diferencias no deberían ser demasiado significativas. Vamos a mostrar algunas imágenes de entrada junto con sus correspondientes salidas.

def show_reconstructions(model, images=X_valid, n_images=5):

    reconstructions = model.predict(images[:n_images])

    fig = plt.figure(figsize=(n_images * 1.5, 3))

    for image_index in range(n_images):

        plt.subplot(2, n_images, 1 + image_index)

        plot_image(images[image_index])

        plt.subplot(2, n_images, 1 + n_images + image_index)

        plot_image(reconstructions[image_index])

        show_reconstructions(stacked_ae)

save_fig("reconstruction_plot")


Autoencoders apilados
Las recostrucciones son reconocibles pero con un poco de pérdida. Necesitamos un entrenamiento más largo para el modelo o construir un codificador-decodificador más profundo. Pero tenemos una red neuronal bastante potente, podemos gestionarla para hacer reconstrucciones perfectas sin que aprenda ningún patrón útil en los datos.

Visualizando el dataset de moda MNIST

Ahora que hemos entrenado nuestro autoencoder apilado, podemos utilizarlo para reducir la dimensionalidad del dataset. Para visualización no devolverá grandes resultados comparado con otros algoritmos de reducción de dimensionalidad, pero una de las grandes ventajas de los autoencoders es que pueden manejar datasets grandes con muchas instancias y muchas características. De este modo, una estrategia es utilizar un autoencoder para reducir la dimensionalidad hasta un nivel razonable, y entonces utilizar otro algoritmo de reducción de dimensionalidad para visualización. Utilizaremos esta estrategia para visualizar el dataset de moda MNIST. Primero utilizaremos el codificador de nuestro autoencoder apilado para reducir la dimensionalidad por debajo de 30, y luego utilizaremos la implementación de Scikit-Learn de un algoritmo t-SNE  para reducir la dimensionalidad a 2 para visualizarlo.

np.random.seed(42)

from sklearn.manifold import TSNE

X_valid_compressed = stacked_encoder.predict(X_valid)

tsne = TSNE()

X_valid_2D = tsne.fit_transform(X_valid_compressed)

X_valid_2D = (X_valid_2D - X_valid_2D.min()) / (X_valid_2D.max() - X_valid_2D.min())

plt.scatter(X_valid_2D[:, 0], X_valid_2D[:, 1], c=y_valid, s=10, cmap="tab10")

plt.axis("off")

plt.show()

El diagrama no es muy bonito, si queremos hacer un poco más vistoso hacemos:

# adaptado de https://scikit-learn.org/stable/auto_examples/manifold/plot_lle_digits.html

plt.figure(figsize=(10, 8))

cmap = plt.cm.tab10

plt.scatter(X_valid_2D[:, 0], X_valid_2D[:, 1], c=y_valid, s=10, cmap=cmap)

image_positions = np.array([[1., 1.]])

for index, position in enumerate(X_valid_2D):

    dist = np.sum((position - image_positions) ** 2, axis=1)

    if np.min(dist) > 0.02: # si está más lejos de otras imágenes

        image_positions = np.r_[image_positions, [position]]

        imagebox = mpl.offsetbox.AnnotationBbox(

            mpl.offsetbox.OffsetImage(X_valid[index], cmap="binary"),

            position, bboxprops={"edgecolor": cmap(y_valid[index]), "lw": 2})

        plt.gca().add_artist(imagebox)

plt.axis("off")

save_fig("visualizacion_mnist_moda")

plt.show()

Esto devuelve como resultado un gráfico más amplio y con algunas imágenes como ejemplo. El algoritmo t-SNE identifica varios grupos razonablemente bien, representa cada clase con un color diferente.

Visualizando el dataset de moda MNIST
De este modo los autoencoders pueden ser utilizados para reducción de dimensionalidad. Otra aplicación es para preentrenamientp 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”