Menu iconMenu icon
Aprendizaje Profundo Generativo Edición Actualizada

Capítulo 5: Explorando Autoencoders Variacionales (VAEs)

5.1 Entendiendo los VAEs

En este capítulo integral, nos embarcaremos en un viaje esclarecedor para descubrir el fascinante mundo de los Autoencoders Variacionales (VAEs). Los VAEs son una clase potente de modelos generativos que combinan hábilmente los principios de las redes neuronales y el modelado probabilístico, dando lugar a una herramienta computacional única con capacidades poderosas.

Lo que distingue a los VAEs es su capacidad inigualable para aprender representaciones latentes significativas y de alta calidad de los datos. Estas representaciones pueden ser aprovechadas para una multitud de propósitos, incluidos, pero no limitados a, generar nuevas muestras que imiten los datos de entrenamiento, comprimir los datos para un almacenamiento eficiente y diversas otras aplicaciones emocionantes que abarcan numerosos campos e industrias.

Nuestra inmersión profunda nos llevará a través de los fundamentos teóricos de los VAEs. Nos esforzaremos por comprender completamente su arquitectura compleja pero elegante, y cómo contribuye a su impresionante funcionalidad. Como una demostración práctica de la teoría, nos arremangaremos y gradualmente implementaremos un VAE desde cero. Esta experiencia práctica está diseñada para proporcionar una comprensión intuitiva de cómo interactúan los diferentes componentes para generar datos.

Para cuando termines este capítulo, no solo tendrás una comprensión sólida del funcionamiento interno de los VAEs, sino que también estarás equipado con el conocimiento práctico de cómo aplicarlos para abordar problemas del mundo real. Estarás listo para aprovechar el poder de los VAEs en tus propios proyectos de ciencia de datos, empujando los límites de lo que es posible con el modelado generativo.

Los Autoencoders Variacionales, también conocidos como VAEs, son un tipo único de modelo generativo. Estos modelos están diseñados con el objetivo específico de aprender a representar datos de manera efectiva y eficiente en un espacio latente de menor dimensión.

El espacio latente aquí es simplemente un constructo matemático que tiene la intención de condensar y capturar las características clave de los datos. Al representar los datos en esta forma más concentrada, se vuelve factible generar nuevas muestras de datos que tengan una notable similitud con los datos originales, esencialmente imitando las características clave de los datos originales.

Los VAEs se construyen a partir de dos componentes esenciales: el codificador y el decodificador. El codificador, como su nombre sugiere, es responsable de codificar, o mapear, los datos de entrada a una distribución latente específica. Esta distribución latente encapsula las características críticas de los datos en una forma compacta.

Por otro lado, el componente decodificador de los VAEs funciona en la dirección inversa. Mapea o traduce las muestras que se extraen de esta distribución latente de vuelta al espacio de datos. Este proceso implica esencialmente la generación de nuevas muestras de datos que son análogas a los datos originales, basándose en la representación condensada en el espacio latente. Así, a través de una combinación de procesos de codificación y decodificación, los VAEs pueden generar nuevas muestras de datos que son similares a los datos originales.

5.1.1 Fundamentos Teóricos

Los fundamentos teóricos de los Autoencoders Variacionales (VAEs) están enraizados en el concepto de inferencia variacional. Esta técnica se utiliza para aproximar distribuciones de probabilidad complejas.

A diferencia de los autoencoders tradicionales, que mapean los datos de entrada a un espacio latente determinista, los VAEs introducen un enfoque probabilístico a este proceso. En lugar de mapear cada entrada a un solo punto en el espacio latente, los VAEs mapean las entradas a una distribución sobre el espacio latente. Esta diferencia sutil permite a los VAEs capturar la incertidumbre y variabilidad inherentes en los datos, haciéndolos una herramienta potente para tareas como generar nuevas muestras que se asemejan a los datos de entrenamiento o comprimir datos para un almacenamiento eficiente.

El objetivo principal de un VAE es maximizar la probabilidad de los datos bajo el modelo. Esto esencialmente significa que el modelo busca encontrar la configuración más probable de parámetros que podría haber generado los datos observados. Simultáneamente, también asegura que el espacio latente se adhiera a una distribución conocida, típicamente una Gaussiana. Esta distribución conocida, referida como la prior, generalmente se elige por su conveniencia matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente incluso antes de observar cualquier dato.

Lograr este objetivo dual es posible mediante la optimización del Límite Inferior de la Evidencia (ELBO, por sus siglas en inglés), una cantidad derivada de los principios de la inferencia variacional. El ELBO consiste en dos términos: la Pérdida de Reconstrucción y la Divergencia KL.

La Pérdida de Reconstrucción es una medida de qué tan bien la parte decodificadora del VAE puede reconstruir los datos de entrada a partir de la representación latente. En esencia, cuantifica la discrepancia entre los datos originales y los datos regenerados desde el espacio latente, con una menor pérdida de reconstrucción indicando un mejor desempeño del VAE.

La Divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución prior (por ejemplo, una Gaussiana estándar). Al minimizar la Divergencia KL, el VAE se ve incentivado a no desviarse drásticamente de nuestras suposiciones previas sobre el espacio latente.

Al optimizar estos dos componentes del ELBO, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden ser utilizadas para una variedad de aplicaciones. Este equilibrio entre la fidelidad de los datos (a través de la pérdida de reconstrucción) y la adherencia a creencias previas (a través de la divergencia KL) es lo que hace a los VAEs una herramienta única y poderosa en el mundo del modelado generativo.

Matemáticamente:

ELBO=E
q(z∣x)

[logp(x∣z)]−KL(q(z∣x)∥p(z))

Donde:

  • ( q(z|x) ) es la aproximación del codificador de la distribución posterior.
  • ( p(x|z) ) es la verosimilitud del decodificador de los datos dados el variable latente.
  • ( p(z) ) es la distribución previa sobre los variables latentes, típicamente una distribución normal estándar.

5.1.2 Una Introducción a la Arquitectura de VAE

La arquitectura de un Autoencoder Variacional (VAE) consta de dos redes neuronales principales: el codificador y el decodificador. La función de la red del codificador es comprimir los datos de entrada, típicamente de alta dimensión, en una representación compacta en el espacio latente.

Este espacio latente, a menudo de menor dimensión, sirve como un cuello de botella que codifica las características esenciales de los datos de entrada. Posteriormente, entra en juego la red del decodificador. El decodificador toma la representación comprimida en el espacio latente y reconstruye los datos originales a partir de ella.

Esta reconstrucción es un intento de reflejar los datos de entrada originales lo más fielmente posible, permitiendo así que el VAE genere nuevos datos que compartan características similares con el conjunto de datos original.

Codificador:

El codificador juega un papel crucial en el proceso de entrenamiento del modelo. Su función principal es aceptar los datos de entrada, procesarlos y luego producir los parámetros que definen la distribución latente. Estos parámetros típicamente consisten en la media y la varianza.

Durante la fase de entrenamiento, las variables latentes, que son cruciales para los procesos de aprendizaje y predicción del modelo, se muestrean a partir de esta distribución. Este proceso de muestreo permite que el modelo genere un conjunto diverso de salidas y le ayuda a aprender la estructura subyacente de los datos de manera más efectiva.

Decodificador:

La función principal del decodificador es tomar las variables latentes muestreadas, que fueron extraídas y transformadas por el codificador, y procesarlas para generar los datos reconstruidos. Estos datos reconstruidos son una aproximación cercana a la entrada original.

El objetivo principal de este proceso es garantizar que se conserven las características clave de los datos de entrada, lo que permite al modelo lograr su objetivo de compresión de datos y reducción de ruido.

El codificador y el decodificador se entrenan simultáneamente para minimizar la pérdida de reconstrucción y la divergencia KL.

Ejemplo: Código de Arquitectura de VAE

Empecemos implementando la arquitectura de VAE usando TensorFlow y Keras:

import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Lambda, Layer
from tensorflow.keras.models import Model
from tensorflow.keras.losses import mse
from tensorflow.keras import backend as K

# Define the sampling layer
class Sampling(Layer):
    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon

# Encoder architecture
def build_encoder(input_shape, latent_dim):
    inputs = Input(shape=input_shape)
    x = Dense(512, activation='relu')(inputs)
    x = Dense(256, activation='relu')(x)
    z_mean = Dense(latent_dim, name='z_mean')(x)
    z_log_var = Dense(latent_dim, name='z_log_var')(x)
    z = Sampling()([z_mean, z_log_var])
    return Model(inputs, [z_mean, z_log_var, z], name='encoder')

# Decoder architecture
def build_decoder(latent_dim, output_shape):
    latent_inputs = Input(shape=(latent_dim,))
    x = Dense(256, activation='relu')(latent_inputs)
    x = Dense(512, activation='relu')(x)
    outputs = Dense(output_shape, activation='sigmoid')(x)
    return Model(latent_inputs, outputs, name='decoder')

# VAE architecture
input_shape = (784,)
latent_dim = 2

encoder = build_encoder(input_shape, latent_dim)
decoder = build_decoder(latent_dim, input_shape[0])

# Instantiate VAE
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')

El script se divide en las siguientes partes:

  1. Importar las bibliotecas necesarias: TensorFlow y Keras (una biblioteca de redes neuronales fácil de usar que se ejecuta sobre TensorFlow).
  2. Definir una capa de Muestreo (Sampling): Esta es una capa personalizada utilizada en el codificador del VAE para muestrear de la distribución aprendida. Utiliza el truco de reparametrización para permitir que los gradientes pasen a través de la capa.
  3. Definir una función de codificador: El modelo de codificador toma una entrada, la pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce dos vectores: un vector de medias (z_mean) y un vector de log varianza (z_log_var). La capa de Muestreo luego muestrea un punto de la distribución definida por estos vectores.
  4. Definir una función de decodificador: El modelo de decodificador toma un vector generado por el codificador, lo pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce un vector del mismo tamaño que los datos de entrada originales.
  5. Crear el modelo VAE: El modelo VAE se crea vinculando los modelos de codificador y decodificador.

El VAE puede usarse para generar nuevos datos similares a los datos de entrenamiento, lo que lo hace útil para tareas como eliminación de ruido, detección de anomalías y generación de datos.

5.1.3 Una Introducción al Entrenamiento del VAE

Entrenar el VAE implica minimizar la función de pérdida, que es una combinación de la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción puede medirse utilizando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo de los datos.

La pérdida de reconstrucción mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Si la reconstrucción es precisa, los datos reconstruidos coincidirán estrechamente con los datos originales, lo que lleva a una menor pérdida de reconstrucción. Por otro lado, si la reconstrucción es inexacta, los datos reconstruidos diferirán significativamente de los datos originales, lo que resultará en una mayor pérdida de reconstrucción. La pérdida de reconstrucción puede calcularse usando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo del tipo de datos.

La divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución previa (típicamente una Gaussiana estándar). Al minimizar la divergencia KL, se fomenta que el VAE no se desvíe drásticamente de nuestras suposiciones previas sobre el espacio latente.

El equilibrio entre reducir la pérdida de reconstrucción y minimizar la divergencia KL es lo que hace que entrenar un VAE sea una tarea compleja pero gratificante. Al optimizar estos dos componentes, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden utilizarse para diversas aplicaciones, empujando los límites de lo que es posible con el modelado generativo.

Función de Pérdida:
VAE Loss=Reconstruction Loss+KL Divergence

Ejemplo: Código de Entrenamiento

# Define the VAE loss
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = mse(inputs, outputs)
    reconstruction_loss *= input_shape[0]
    kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
    kl_loss = K.sum(kl_loss, axis=-1)
    kl_loss *= -0.5
    return K.mean(reconstruction_loss + kl_loss)

# Compile the VAE
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

# Load and preprocess the dataset (e.g., MNIST)
(x_train, _), (x_test, _) = tf.keras.datasets.mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((x_train.shape[0], np.prod(x_train.shape[1:])))
x_test = x_test.reshape((x_test.shape[0], np.prod(x_test.shape[1:])))

# Train the VAE
vae.fit(x_train, x_train, epochs=50, batch_size=128, validation_data=(x_test, x_test))

En este ejemplo:

La primera parte del código define la función de pérdida para el VAE. Esta función de pérdida es una combinación de dos componentes: la pérdida de reconstrucción y la divergencia de Kullback-Leibler (KL). La pérdida de reconstrucción se calcula utilizando el error cuadrático medio (mse) entre las entradas originales y las salidas reconstruidas. Esta pérdida mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Una pérdida de reconstrucción más baja indica que el modelo puede reconstruir eficazmente los datos de entrada, lo cual es una propiedad deseada en un buen autoencoder.

La divergencia KL, por otro lado, actúa como un término de regularización en la función de pérdida. Mide cuánto se desvía la distribución de las variables latentes aprendidas de una distribución normal estándar. La distribución normal estándar se usa a menudo como la distribución previa para las variables latentes en los VAEs debido a su simplicidad matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato. Al minimizar la divergencia KL, se anima al VAE a mantener la distribución latente aprendida cercana a la distribución previa.

Después de definir la función de pérdida, se compila el modelo VAE. Durante este paso, se utiliza el optimizador Adam, que es una elección popular para entrenar modelos de aprendizaje profundo porque combina las ventajas de dos otras extensiones del descenso de gradiente estocástico: AdaGrad y RMSProp. La función de pérdida utilizada para la compilación es la definida anteriormente, que toma como entradas las entradas originales, las salidas reconstruidas y los parámetros de la distribución latente aprendida.

La siguiente parte del código trata sobre la carga y el preprocesamiento del conjunto de datos. En este caso, se utiliza el conjunto de datos MNIST, que es una gran base de datos de dígitos escritos a mano que se usa comúnmente para entrenar varios sistemas de procesamiento de imágenes. Las imágenes se cargan, se normalizan para tener valores de píxeles entre 0 y 1, y se remodelan de matrices 2D a matrices 1D (o vectores), que es la forma de entrada requerida para el VAE.

Finalmente, el modelo VAE se entrena utilizando el conjunto de datos MNIST preprocesado. El modelo se entrena durante 50 épocas con un tamaño de lote de 128. Los mismos datos se utilizan tanto para la entrada como para el objetivo porque los VAEs son modelos de aprendizaje no supervisado que intentan recrear su entrada. Los datos de validación utilizados durante el entrenamiento son los datos de prueba del conjunto de datos MNIST.

Al ejecutar este código, puedes entrenar un VAE desde cero y comprender su funcionamiento interno. Sin embargo, ten en cuenta que el proceso de entrenamiento podría llevar un tiempo en completarse, especialmente si no estás utilizando una máquina potente o una GPU.

5.1.4 Muestreo del Espacio Latente

Una vez que el VAE está entrenado, podemos muestrear del espacio latente para generar nuevos datos. Esto implica muestrear variables latentes de la distribución previa (una distribución gaussiana estándar) y pasarlas a través del decodificador para generar nuevas muestras.

El proceso de generación de nuevos datos implica el muestreo del espacio latente. Esto se hace extrayendo variables latentes de la distribución previa, que suele ser una distribución gaussiana estándar. Esta distribución previa se elige debido a su conveniencia matemática y porque encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato.

Estas variables latentes muestreadas se pasan luego a través del componente decodificador del VAE. El decodificador es responsable de traducir las muestras extraídas de la distribución latente de vuelta al espacio de datos. Es durante este proceso que se generan nuevas muestras de datos. Estas nuevas muestras, en esencia, son una recreación basada en la representación condensada en el espacio latente.

Así, el proceso de generación de nuevos datos a partir del VAE implica una combinación de codificación de los datos de entrada en una distribución latente específica y luego la decodificación o traducción de muestras de esta distribución para generar nuevas muestras que sean similares a los datos originales.

Al aprovechar el poder de los Autoencoders Variacionales de esta manera, podemos crear una variedad de nuevas muestras de datos que imitan de cerca los datos de entrenamiento originales, y esto puede ser útil en una variedad de aplicaciones de ciencia de datos y aprendizaje automático.

Ejemplo: Código de Muestreo

import matplotlib.pyplot as plt
import numpy as np

# Generate new samples
def generate_samples(decoder, latent_dim, n_samples=10):
    random_latent_vectors = np.random.normal(size=(n_samples, latent_dim))
    generated_images = decoder.predict(random_latent_vectors)
    generated_images = generated_images.reshape((n_samples, 28, 28))
    return generated_images

# Plot generated samples
generated_images = generate_samples(decoder, latent_dim)
plt.figure(figsize=(10, 2))
for i in range(generated_images.shape[0]):
    plt.subplot(1, generated_images.shape[0], i + 1)
    plt.imshow(generated_images[i], cmap='gray')
    plt.axis('off')
plt.show()

En este ejemplo:

La función generate_samples(decoder, latent_dim, n_samples=10) genera una cantidad especificada de muestras (por defecto, 10) utilizando el modelo decodificador. El decodificador es uno de los dos componentes principales de un VAE (el otro es el codificador) y es responsable de generar nuevas muestras de datos a partir del espacio latente. El espacio latente es una representación de menor dimensión de los datos y es donde el VAE codifica las características clave de los datos.

La función comienza generando vectores latentes aleatorios a partir de una distribución normal. El tamaño de estos vectores está determinado por los parámetros n_samples y latent_dimn_samples es el número de muestras a generar y latent_dim es la dimensionalidad del espacio latente.

La línea decoder.predict(random_latent_vectors) utiliza el modelo decodificador para generar nuevas muestras de datos a partir de estos vectores latentes aleatorios. Estas muestras generadas se remodelan en imágenes con un formato de 28x28 píxeles, que es un tamaño común para las imágenes en conjuntos de datos como MNIST. Las imágenes remodeladas son devueltas por la función.

El siguiente bloque de código visualiza estas imágenes generadas en una sola fila utilizando Matplotlib. Crea una nueva figura, recorre las imágenes generadas y añade cada una a la figura como un subplot. Las imágenes se muestran en escala de grises, según lo especificado por cmap='gray', y las etiquetas de los ejes se desactivan con plt.axis('off'). Finalmente, se llama a plt.show() para mostrar la figura.

Este proceso de generar y visualizar nuevas muestras es una parte crucial del trabajo con VAEs y otros modelos generativos. Al visualizar las muestras generadas, podemos tener una idea de qué tan bien ha aprendido el modelo a imitar los datos de entrenamiento y si el espacio latente está estructurado de una manera útil.

Resumen

En la primera sección de este capítulo, profundizamos en los conceptos fundamentales y cruciales que subyacen a los Autoencoders Variacionales (VAEs), un tipo innovador y potente de modelo generativo. Nuestra exploración nos llevó a comprender la forma única en que los VAEs utilizan la inferencia variacional como un medio para aprender e internalizar una representación latente probabilística de los datos. Esto se logra combinando hábilmente las fortalezas de dos redes cruciales: un codificador y un decodificador.

Llevamos nuestra comprensión un paso más allá implementando prácticamente la arquitectura de los VAEs. Esto nos permitió comprender la mecánica y las sutilezas del modelo de una manera práctica. El conjunto de datos MNIST sirvió como la plataforma perfecta para este ejercicio, siendo un estándar en el campo para evaluar el rendimiento.

Además de implementar la arquitectura, también entrenamos el modelo en el conjunto de datos MNIST. Este proceso ilustró las capacidades de aprendizaje de los VAEs, ampliando nuestra comprensión de su potencial y limitaciones. Después del entrenamiento, demostramos el poder de los VAEs muestreando del espacio latente para generar nuevas imágenes no vistas. Esta aplicación práctica mostró la utilidad real de los VAEs y su potencial para crear nuevos datos realistas.

En conclusión, los VAEs son una herramienta increíblemente poderosa para la modelización generativa. Tienen la capacidad única de permitir la generación de una amplia gama de datos realistas y diversos. Al mismo tiempo, proporcionan representaciones latentes significativas, añadiendo otra capa de utilidad a su función. Con su combinación de utilidad práctica e intriga teórica, los VAEs ofrecen una vía prometedora para la exploración y el desarrollo futuro en el campo de la modelización generativa.

5.1 Entendiendo los VAEs

En este capítulo integral, nos embarcaremos en un viaje esclarecedor para descubrir el fascinante mundo de los Autoencoders Variacionales (VAEs). Los VAEs son una clase potente de modelos generativos que combinan hábilmente los principios de las redes neuronales y el modelado probabilístico, dando lugar a una herramienta computacional única con capacidades poderosas.

Lo que distingue a los VAEs es su capacidad inigualable para aprender representaciones latentes significativas y de alta calidad de los datos. Estas representaciones pueden ser aprovechadas para una multitud de propósitos, incluidos, pero no limitados a, generar nuevas muestras que imiten los datos de entrenamiento, comprimir los datos para un almacenamiento eficiente y diversas otras aplicaciones emocionantes que abarcan numerosos campos e industrias.

Nuestra inmersión profunda nos llevará a través de los fundamentos teóricos de los VAEs. Nos esforzaremos por comprender completamente su arquitectura compleja pero elegante, y cómo contribuye a su impresionante funcionalidad. Como una demostración práctica de la teoría, nos arremangaremos y gradualmente implementaremos un VAE desde cero. Esta experiencia práctica está diseñada para proporcionar una comprensión intuitiva de cómo interactúan los diferentes componentes para generar datos.

Para cuando termines este capítulo, no solo tendrás una comprensión sólida del funcionamiento interno de los VAEs, sino que también estarás equipado con el conocimiento práctico de cómo aplicarlos para abordar problemas del mundo real. Estarás listo para aprovechar el poder de los VAEs en tus propios proyectos de ciencia de datos, empujando los límites de lo que es posible con el modelado generativo.

Los Autoencoders Variacionales, también conocidos como VAEs, son un tipo único de modelo generativo. Estos modelos están diseñados con el objetivo específico de aprender a representar datos de manera efectiva y eficiente en un espacio latente de menor dimensión.

El espacio latente aquí es simplemente un constructo matemático que tiene la intención de condensar y capturar las características clave de los datos. Al representar los datos en esta forma más concentrada, se vuelve factible generar nuevas muestras de datos que tengan una notable similitud con los datos originales, esencialmente imitando las características clave de los datos originales.

Los VAEs se construyen a partir de dos componentes esenciales: el codificador y el decodificador. El codificador, como su nombre sugiere, es responsable de codificar, o mapear, los datos de entrada a una distribución latente específica. Esta distribución latente encapsula las características críticas de los datos en una forma compacta.

Por otro lado, el componente decodificador de los VAEs funciona en la dirección inversa. Mapea o traduce las muestras que se extraen de esta distribución latente de vuelta al espacio de datos. Este proceso implica esencialmente la generación de nuevas muestras de datos que son análogas a los datos originales, basándose en la representación condensada en el espacio latente. Así, a través de una combinación de procesos de codificación y decodificación, los VAEs pueden generar nuevas muestras de datos que son similares a los datos originales.

5.1.1 Fundamentos Teóricos

Los fundamentos teóricos de los Autoencoders Variacionales (VAEs) están enraizados en el concepto de inferencia variacional. Esta técnica se utiliza para aproximar distribuciones de probabilidad complejas.

A diferencia de los autoencoders tradicionales, que mapean los datos de entrada a un espacio latente determinista, los VAEs introducen un enfoque probabilístico a este proceso. En lugar de mapear cada entrada a un solo punto en el espacio latente, los VAEs mapean las entradas a una distribución sobre el espacio latente. Esta diferencia sutil permite a los VAEs capturar la incertidumbre y variabilidad inherentes en los datos, haciéndolos una herramienta potente para tareas como generar nuevas muestras que se asemejan a los datos de entrenamiento o comprimir datos para un almacenamiento eficiente.

El objetivo principal de un VAE es maximizar la probabilidad de los datos bajo el modelo. Esto esencialmente significa que el modelo busca encontrar la configuración más probable de parámetros que podría haber generado los datos observados. Simultáneamente, también asegura que el espacio latente se adhiera a una distribución conocida, típicamente una Gaussiana. Esta distribución conocida, referida como la prior, generalmente se elige por su conveniencia matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente incluso antes de observar cualquier dato.

Lograr este objetivo dual es posible mediante la optimización del Límite Inferior de la Evidencia (ELBO, por sus siglas en inglés), una cantidad derivada de los principios de la inferencia variacional. El ELBO consiste en dos términos: la Pérdida de Reconstrucción y la Divergencia KL.

La Pérdida de Reconstrucción es una medida de qué tan bien la parte decodificadora del VAE puede reconstruir los datos de entrada a partir de la representación latente. En esencia, cuantifica la discrepancia entre los datos originales y los datos regenerados desde el espacio latente, con una menor pérdida de reconstrucción indicando un mejor desempeño del VAE.

La Divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución prior (por ejemplo, una Gaussiana estándar). Al minimizar la Divergencia KL, el VAE se ve incentivado a no desviarse drásticamente de nuestras suposiciones previas sobre el espacio latente.

Al optimizar estos dos componentes del ELBO, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden ser utilizadas para una variedad de aplicaciones. Este equilibrio entre la fidelidad de los datos (a través de la pérdida de reconstrucción) y la adherencia a creencias previas (a través de la divergencia KL) es lo que hace a los VAEs una herramienta única y poderosa en el mundo del modelado generativo.

Matemáticamente:

ELBO=E
q(z∣x)

[logp(x∣z)]−KL(q(z∣x)∥p(z))

Donde:

  • ( q(z|x) ) es la aproximación del codificador de la distribución posterior.
  • ( p(x|z) ) es la verosimilitud del decodificador de los datos dados el variable latente.
  • ( p(z) ) es la distribución previa sobre los variables latentes, típicamente una distribución normal estándar.

5.1.2 Una Introducción a la Arquitectura de VAE

La arquitectura de un Autoencoder Variacional (VAE) consta de dos redes neuronales principales: el codificador y el decodificador. La función de la red del codificador es comprimir los datos de entrada, típicamente de alta dimensión, en una representación compacta en el espacio latente.

Este espacio latente, a menudo de menor dimensión, sirve como un cuello de botella que codifica las características esenciales de los datos de entrada. Posteriormente, entra en juego la red del decodificador. El decodificador toma la representación comprimida en el espacio latente y reconstruye los datos originales a partir de ella.

Esta reconstrucción es un intento de reflejar los datos de entrada originales lo más fielmente posible, permitiendo así que el VAE genere nuevos datos que compartan características similares con el conjunto de datos original.

Codificador:

El codificador juega un papel crucial en el proceso de entrenamiento del modelo. Su función principal es aceptar los datos de entrada, procesarlos y luego producir los parámetros que definen la distribución latente. Estos parámetros típicamente consisten en la media y la varianza.

Durante la fase de entrenamiento, las variables latentes, que son cruciales para los procesos de aprendizaje y predicción del modelo, se muestrean a partir de esta distribución. Este proceso de muestreo permite que el modelo genere un conjunto diverso de salidas y le ayuda a aprender la estructura subyacente de los datos de manera más efectiva.

Decodificador:

La función principal del decodificador es tomar las variables latentes muestreadas, que fueron extraídas y transformadas por el codificador, y procesarlas para generar los datos reconstruidos. Estos datos reconstruidos son una aproximación cercana a la entrada original.

El objetivo principal de este proceso es garantizar que se conserven las características clave de los datos de entrada, lo que permite al modelo lograr su objetivo de compresión de datos y reducción de ruido.

El codificador y el decodificador se entrenan simultáneamente para minimizar la pérdida de reconstrucción y la divergencia KL.

Ejemplo: Código de Arquitectura de VAE

Empecemos implementando la arquitectura de VAE usando TensorFlow y Keras:

import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Lambda, Layer
from tensorflow.keras.models import Model
from tensorflow.keras.losses import mse
from tensorflow.keras import backend as K

# Define the sampling layer
class Sampling(Layer):
    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon

# Encoder architecture
def build_encoder(input_shape, latent_dim):
    inputs = Input(shape=input_shape)
    x = Dense(512, activation='relu')(inputs)
    x = Dense(256, activation='relu')(x)
    z_mean = Dense(latent_dim, name='z_mean')(x)
    z_log_var = Dense(latent_dim, name='z_log_var')(x)
    z = Sampling()([z_mean, z_log_var])
    return Model(inputs, [z_mean, z_log_var, z], name='encoder')

# Decoder architecture
def build_decoder(latent_dim, output_shape):
    latent_inputs = Input(shape=(latent_dim,))
    x = Dense(256, activation='relu')(latent_inputs)
    x = Dense(512, activation='relu')(x)
    outputs = Dense(output_shape, activation='sigmoid')(x)
    return Model(latent_inputs, outputs, name='decoder')

# VAE architecture
input_shape = (784,)
latent_dim = 2

encoder = build_encoder(input_shape, latent_dim)
decoder = build_decoder(latent_dim, input_shape[0])

# Instantiate VAE
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')

El script se divide en las siguientes partes:

  1. Importar las bibliotecas necesarias: TensorFlow y Keras (una biblioteca de redes neuronales fácil de usar que se ejecuta sobre TensorFlow).
  2. Definir una capa de Muestreo (Sampling): Esta es una capa personalizada utilizada en el codificador del VAE para muestrear de la distribución aprendida. Utiliza el truco de reparametrización para permitir que los gradientes pasen a través de la capa.
  3. Definir una función de codificador: El modelo de codificador toma una entrada, la pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce dos vectores: un vector de medias (z_mean) y un vector de log varianza (z_log_var). La capa de Muestreo luego muestrea un punto de la distribución definida por estos vectores.
  4. Definir una función de decodificador: El modelo de decodificador toma un vector generado por el codificador, lo pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce un vector del mismo tamaño que los datos de entrada originales.
  5. Crear el modelo VAE: El modelo VAE se crea vinculando los modelos de codificador y decodificador.

El VAE puede usarse para generar nuevos datos similares a los datos de entrenamiento, lo que lo hace útil para tareas como eliminación de ruido, detección de anomalías y generación de datos.

5.1.3 Una Introducción al Entrenamiento del VAE

Entrenar el VAE implica minimizar la función de pérdida, que es una combinación de la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción puede medirse utilizando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo de los datos.

La pérdida de reconstrucción mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Si la reconstrucción es precisa, los datos reconstruidos coincidirán estrechamente con los datos originales, lo que lleva a una menor pérdida de reconstrucción. Por otro lado, si la reconstrucción es inexacta, los datos reconstruidos diferirán significativamente de los datos originales, lo que resultará en una mayor pérdida de reconstrucción. La pérdida de reconstrucción puede calcularse usando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo del tipo de datos.

La divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución previa (típicamente una Gaussiana estándar). Al minimizar la divergencia KL, se fomenta que el VAE no se desvíe drásticamente de nuestras suposiciones previas sobre el espacio latente.

El equilibrio entre reducir la pérdida de reconstrucción y minimizar la divergencia KL es lo que hace que entrenar un VAE sea una tarea compleja pero gratificante. Al optimizar estos dos componentes, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden utilizarse para diversas aplicaciones, empujando los límites de lo que es posible con el modelado generativo.

Función de Pérdida:
VAE Loss=Reconstruction Loss+KL Divergence

Ejemplo: Código de Entrenamiento

# Define the VAE loss
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = mse(inputs, outputs)
    reconstruction_loss *= input_shape[0]
    kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
    kl_loss = K.sum(kl_loss, axis=-1)
    kl_loss *= -0.5
    return K.mean(reconstruction_loss + kl_loss)

# Compile the VAE
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

# Load and preprocess the dataset (e.g., MNIST)
(x_train, _), (x_test, _) = tf.keras.datasets.mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((x_train.shape[0], np.prod(x_train.shape[1:])))
x_test = x_test.reshape((x_test.shape[0], np.prod(x_test.shape[1:])))

# Train the VAE
vae.fit(x_train, x_train, epochs=50, batch_size=128, validation_data=(x_test, x_test))

En este ejemplo:

La primera parte del código define la función de pérdida para el VAE. Esta función de pérdida es una combinación de dos componentes: la pérdida de reconstrucción y la divergencia de Kullback-Leibler (KL). La pérdida de reconstrucción se calcula utilizando el error cuadrático medio (mse) entre las entradas originales y las salidas reconstruidas. Esta pérdida mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Una pérdida de reconstrucción más baja indica que el modelo puede reconstruir eficazmente los datos de entrada, lo cual es una propiedad deseada en un buen autoencoder.

La divergencia KL, por otro lado, actúa como un término de regularización en la función de pérdida. Mide cuánto se desvía la distribución de las variables latentes aprendidas de una distribución normal estándar. La distribución normal estándar se usa a menudo como la distribución previa para las variables latentes en los VAEs debido a su simplicidad matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato. Al minimizar la divergencia KL, se anima al VAE a mantener la distribución latente aprendida cercana a la distribución previa.

Después de definir la función de pérdida, se compila el modelo VAE. Durante este paso, se utiliza el optimizador Adam, que es una elección popular para entrenar modelos de aprendizaje profundo porque combina las ventajas de dos otras extensiones del descenso de gradiente estocástico: AdaGrad y RMSProp. La función de pérdida utilizada para la compilación es la definida anteriormente, que toma como entradas las entradas originales, las salidas reconstruidas y los parámetros de la distribución latente aprendida.

La siguiente parte del código trata sobre la carga y el preprocesamiento del conjunto de datos. En este caso, se utiliza el conjunto de datos MNIST, que es una gran base de datos de dígitos escritos a mano que se usa comúnmente para entrenar varios sistemas de procesamiento de imágenes. Las imágenes se cargan, se normalizan para tener valores de píxeles entre 0 y 1, y se remodelan de matrices 2D a matrices 1D (o vectores), que es la forma de entrada requerida para el VAE.

Finalmente, el modelo VAE se entrena utilizando el conjunto de datos MNIST preprocesado. El modelo se entrena durante 50 épocas con un tamaño de lote de 128. Los mismos datos se utilizan tanto para la entrada como para el objetivo porque los VAEs son modelos de aprendizaje no supervisado que intentan recrear su entrada. Los datos de validación utilizados durante el entrenamiento son los datos de prueba del conjunto de datos MNIST.

Al ejecutar este código, puedes entrenar un VAE desde cero y comprender su funcionamiento interno. Sin embargo, ten en cuenta que el proceso de entrenamiento podría llevar un tiempo en completarse, especialmente si no estás utilizando una máquina potente o una GPU.

5.1.4 Muestreo del Espacio Latente

Una vez que el VAE está entrenado, podemos muestrear del espacio latente para generar nuevos datos. Esto implica muestrear variables latentes de la distribución previa (una distribución gaussiana estándar) y pasarlas a través del decodificador para generar nuevas muestras.

El proceso de generación de nuevos datos implica el muestreo del espacio latente. Esto se hace extrayendo variables latentes de la distribución previa, que suele ser una distribución gaussiana estándar. Esta distribución previa se elige debido a su conveniencia matemática y porque encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato.

Estas variables latentes muestreadas se pasan luego a través del componente decodificador del VAE. El decodificador es responsable de traducir las muestras extraídas de la distribución latente de vuelta al espacio de datos. Es durante este proceso que se generan nuevas muestras de datos. Estas nuevas muestras, en esencia, son una recreación basada en la representación condensada en el espacio latente.

Así, el proceso de generación de nuevos datos a partir del VAE implica una combinación de codificación de los datos de entrada en una distribución latente específica y luego la decodificación o traducción de muestras de esta distribución para generar nuevas muestras que sean similares a los datos originales.

Al aprovechar el poder de los Autoencoders Variacionales de esta manera, podemos crear una variedad de nuevas muestras de datos que imitan de cerca los datos de entrenamiento originales, y esto puede ser útil en una variedad de aplicaciones de ciencia de datos y aprendizaje automático.

Ejemplo: Código de Muestreo

import matplotlib.pyplot as plt
import numpy as np

# Generate new samples
def generate_samples(decoder, latent_dim, n_samples=10):
    random_latent_vectors = np.random.normal(size=(n_samples, latent_dim))
    generated_images = decoder.predict(random_latent_vectors)
    generated_images = generated_images.reshape((n_samples, 28, 28))
    return generated_images

# Plot generated samples
generated_images = generate_samples(decoder, latent_dim)
plt.figure(figsize=(10, 2))
for i in range(generated_images.shape[0]):
    plt.subplot(1, generated_images.shape[0], i + 1)
    plt.imshow(generated_images[i], cmap='gray')
    plt.axis('off')
plt.show()

En este ejemplo:

La función generate_samples(decoder, latent_dim, n_samples=10) genera una cantidad especificada de muestras (por defecto, 10) utilizando el modelo decodificador. El decodificador es uno de los dos componentes principales de un VAE (el otro es el codificador) y es responsable de generar nuevas muestras de datos a partir del espacio latente. El espacio latente es una representación de menor dimensión de los datos y es donde el VAE codifica las características clave de los datos.

La función comienza generando vectores latentes aleatorios a partir de una distribución normal. El tamaño de estos vectores está determinado por los parámetros n_samples y latent_dimn_samples es el número de muestras a generar y latent_dim es la dimensionalidad del espacio latente.

La línea decoder.predict(random_latent_vectors) utiliza el modelo decodificador para generar nuevas muestras de datos a partir de estos vectores latentes aleatorios. Estas muestras generadas se remodelan en imágenes con un formato de 28x28 píxeles, que es un tamaño común para las imágenes en conjuntos de datos como MNIST. Las imágenes remodeladas son devueltas por la función.

El siguiente bloque de código visualiza estas imágenes generadas en una sola fila utilizando Matplotlib. Crea una nueva figura, recorre las imágenes generadas y añade cada una a la figura como un subplot. Las imágenes se muestran en escala de grises, según lo especificado por cmap='gray', y las etiquetas de los ejes se desactivan con plt.axis('off'). Finalmente, se llama a plt.show() para mostrar la figura.

Este proceso de generar y visualizar nuevas muestras es una parte crucial del trabajo con VAEs y otros modelos generativos. Al visualizar las muestras generadas, podemos tener una idea de qué tan bien ha aprendido el modelo a imitar los datos de entrenamiento y si el espacio latente está estructurado de una manera útil.

Resumen

En la primera sección de este capítulo, profundizamos en los conceptos fundamentales y cruciales que subyacen a los Autoencoders Variacionales (VAEs), un tipo innovador y potente de modelo generativo. Nuestra exploración nos llevó a comprender la forma única en que los VAEs utilizan la inferencia variacional como un medio para aprender e internalizar una representación latente probabilística de los datos. Esto se logra combinando hábilmente las fortalezas de dos redes cruciales: un codificador y un decodificador.

Llevamos nuestra comprensión un paso más allá implementando prácticamente la arquitectura de los VAEs. Esto nos permitió comprender la mecánica y las sutilezas del modelo de una manera práctica. El conjunto de datos MNIST sirvió como la plataforma perfecta para este ejercicio, siendo un estándar en el campo para evaluar el rendimiento.

Además de implementar la arquitectura, también entrenamos el modelo en el conjunto de datos MNIST. Este proceso ilustró las capacidades de aprendizaje de los VAEs, ampliando nuestra comprensión de su potencial y limitaciones. Después del entrenamiento, demostramos el poder de los VAEs muestreando del espacio latente para generar nuevas imágenes no vistas. Esta aplicación práctica mostró la utilidad real de los VAEs y su potencial para crear nuevos datos realistas.

En conclusión, los VAEs son una herramienta increíblemente poderosa para la modelización generativa. Tienen la capacidad única de permitir la generación de una amplia gama de datos realistas y diversos. Al mismo tiempo, proporcionan representaciones latentes significativas, añadiendo otra capa de utilidad a su función. Con su combinación de utilidad práctica e intriga teórica, los VAEs ofrecen una vía prometedora para la exploración y el desarrollo futuro en el campo de la modelización generativa.

5.1 Entendiendo los VAEs

En este capítulo integral, nos embarcaremos en un viaje esclarecedor para descubrir el fascinante mundo de los Autoencoders Variacionales (VAEs). Los VAEs son una clase potente de modelos generativos que combinan hábilmente los principios de las redes neuronales y el modelado probabilístico, dando lugar a una herramienta computacional única con capacidades poderosas.

Lo que distingue a los VAEs es su capacidad inigualable para aprender representaciones latentes significativas y de alta calidad de los datos. Estas representaciones pueden ser aprovechadas para una multitud de propósitos, incluidos, pero no limitados a, generar nuevas muestras que imiten los datos de entrenamiento, comprimir los datos para un almacenamiento eficiente y diversas otras aplicaciones emocionantes que abarcan numerosos campos e industrias.

Nuestra inmersión profunda nos llevará a través de los fundamentos teóricos de los VAEs. Nos esforzaremos por comprender completamente su arquitectura compleja pero elegante, y cómo contribuye a su impresionante funcionalidad. Como una demostración práctica de la teoría, nos arremangaremos y gradualmente implementaremos un VAE desde cero. Esta experiencia práctica está diseñada para proporcionar una comprensión intuitiva de cómo interactúan los diferentes componentes para generar datos.

Para cuando termines este capítulo, no solo tendrás una comprensión sólida del funcionamiento interno de los VAEs, sino que también estarás equipado con el conocimiento práctico de cómo aplicarlos para abordar problemas del mundo real. Estarás listo para aprovechar el poder de los VAEs en tus propios proyectos de ciencia de datos, empujando los límites de lo que es posible con el modelado generativo.

Los Autoencoders Variacionales, también conocidos como VAEs, son un tipo único de modelo generativo. Estos modelos están diseñados con el objetivo específico de aprender a representar datos de manera efectiva y eficiente en un espacio latente de menor dimensión.

El espacio latente aquí es simplemente un constructo matemático que tiene la intención de condensar y capturar las características clave de los datos. Al representar los datos en esta forma más concentrada, se vuelve factible generar nuevas muestras de datos que tengan una notable similitud con los datos originales, esencialmente imitando las características clave de los datos originales.

Los VAEs se construyen a partir de dos componentes esenciales: el codificador y el decodificador. El codificador, como su nombre sugiere, es responsable de codificar, o mapear, los datos de entrada a una distribución latente específica. Esta distribución latente encapsula las características críticas de los datos en una forma compacta.

Por otro lado, el componente decodificador de los VAEs funciona en la dirección inversa. Mapea o traduce las muestras que se extraen de esta distribución latente de vuelta al espacio de datos. Este proceso implica esencialmente la generación de nuevas muestras de datos que son análogas a los datos originales, basándose en la representación condensada en el espacio latente. Así, a través de una combinación de procesos de codificación y decodificación, los VAEs pueden generar nuevas muestras de datos que son similares a los datos originales.

5.1.1 Fundamentos Teóricos

Los fundamentos teóricos de los Autoencoders Variacionales (VAEs) están enraizados en el concepto de inferencia variacional. Esta técnica se utiliza para aproximar distribuciones de probabilidad complejas.

A diferencia de los autoencoders tradicionales, que mapean los datos de entrada a un espacio latente determinista, los VAEs introducen un enfoque probabilístico a este proceso. En lugar de mapear cada entrada a un solo punto en el espacio latente, los VAEs mapean las entradas a una distribución sobre el espacio latente. Esta diferencia sutil permite a los VAEs capturar la incertidumbre y variabilidad inherentes en los datos, haciéndolos una herramienta potente para tareas como generar nuevas muestras que se asemejan a los datos de entrenamiento o comprimir datos para un almacenamiento eficiente.

El objetivo principal de un VAE es maximizar la probabilidad de los datos bajo el modelo. Esto esencialmente significa que el modelo busca encontrar la configuración más probable de parámetros que podría haber generado los datos observados. Simultáneamente, también asegura que el espacio latente se adhiera a una distribución conocida, típicamente una Gaussiana. Esta distribución conocida, referida como la prior, generalmente se elige por su conveniencia matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente incluso antes de observar cualquier dato.

Lograr este objetivo dual es posible mediante la optimización del Límite Inferior de la Evidencia (ELBO, por sus siglas en inglés), una cantidad derivada de los principios de la inferencia variacional. El ELBO consiste en dos términos: la Pérdida de Reconstrucción y la Divergencia KL.

La Pérdida de Reconstrucción es una medida de qué tan bien la parte decodificadora del VAE puede reconstruir los datos de entrada a partir de la representación latente. En esencia, cuantifica la discrepancia entre los datos originales y los datos regenerados desde el espacio latente, con una menor pérdida de reconstrucción indicando un mejor desempeño del VAE.

La Divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución prior (por ejemplo, una Gaussiana estándar). Al minimizar la Divergencia KL, el VAE se ve incentivado a no desviarse drásticamente de nuestras suposiciones previas sobre el espacio latente.

Al optimizar estos dos componentes del ELBO, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden ser utilizadas para una variedad de aplicaciones. Este equilibrio entre la fidelidad de los datos (a través de la pérdida de reconstrucción) y la adherencia a creencias previas (a través de la divergencia KL) es lo que hace a los VAEs una herramienta única y poderosa en el mundo del modelado generativo.

Matemáticamente:

ELBO=E
q(z∣x)

[logp(x∣z)]−KL(q(z∣x)∥p(z))

Donde:

  • ( q(z|x) ) es la aproximación del codificador de la distribución posterior.
  • ( p(x|z) ) es la verosimilitud del decodificador de los datos dados el variable latente.
  • ( p(z) ) es la distribución previa sobre los variables latentes, típicamente una distribución normal estándar.

5.1.2 Una Introducción a la Arquitectura de VAE

La arquitectura de un Autoencoder Variacional (VAE) consta de dos redes neuronales principales: el codificador y el decodificador. La función de la red del codificador es comprimir los datos de entrada, típicamente de alta dimensión, en una representación compacta en el espacio latente.

Este espacio latente, a menudo de menor dimensión, sirve como un cuello de botella que codifica las características esenciales de los datos de entrada. Posteriormente, entra en juego la red del decodificador. El decodificador toma la representación comprimida en el espacio latente y reconstruye los datos originales a partir de ella.

Esta reconstrucción es un intento de reflejar los datos de entrada originales lo más fielmente posible, permitiendo así que el VAE genere nuevos datos que compartan características similares con el conjunto de datos original.

Codificador:

El codificador juega un papel crucial en el proceso de entrenamiento del modelo. Su función principal es aceptar los datos de entrada, procesarlos y luego producir los parámetros que definen la distribución latente. Estos parámetros típicamente consisten en la media y la varianza.

Durante la fase de entrenamiento, las variables latentes, que son cruciales para los procesos de aprendizaje y predicción del modelo, se muestrean a partir de esta distribución. Este proceso de muestreo permite que el modelo genere un conjunto diverso de salidas y le ayuda a aprender la estructura subyacente de los datos de manera más efectiva.

Decodificador:

La función principal del decodificador es tomar las variables latentes muestreadas, que fueron extraídas y transformadas por el codificador, y procesarlas para generar los datos reconstruidos. Estos datos reconstruidos son una aproximación cercana a la entrada original.

El objetivo principal de este proceso es garantizar que se conserven las características clave de los datos de entrada, lo que permite al modelo lograr su objetivo de compresión de datos y reducción de ruido.

El codificador y el decodificador se entrenan simultáneamente para minimizar la pérdida de reconstrucción y la divergencia KL.

Ejemplo: Código de Arquitectura de VAE

Empecemos implementando la arquitectura de VAE usando TensorFlow y Keras:

import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Lambda, Layer
from tensorflow.keras.models import Model
from tensorflow.keras.losses import mse
from tensorflow.keras import backend as K

# Define the sampling layer
class Sampling(Layer):
    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon

# Encoder architecture
def build_encoder(input_shape, latent_dim):
    inputs = Input(shape=input_shape)
    x = Dense(512, activation='relu')(inputs)
    x = Dense(256, activation='relu')(x)
    z_mean = Dense(latent_dim, name='z_mean')(x)
    z_log_var = Dense(latent_dim, name='z_log_var')(x)
    z = Sampling()([z_mean, z_log_var])
    return Model(inputs, [z_mean, z_log_var, z], name='encoder')

# Decoder architecture
def build_decoder(latent_dim, output_shape):
    latent_inputs = Input(shape=(latent_dim,))
    x = Dense(256, activation='relu')(latent_inputs)
    x = Dense(512, activation='relu')(x)
    outputs = Dense(output_shape, activation='sigmoid')(x)
    return Model(latent_inputs, outputs, name='decoder')

# VAE architecture
input_shape = (784,)
latent_dim = 2

encoder = build_encoder(input_shape, latent_dim)
decoder = build_decoder(latent_dim, input_shape[0])

# Instantiate VAE
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')

El script se divide en las siguientes partes:

  1. Importar las bibliotecas necesarias: TensorFlow y Keras (una biblioteca de redes neuronales fácil de usar que se ejecuta sobre TensorFlow).
  2. Definir una capa de Muestreo (Sampling): Esta es una capa personalizada utilizada en el codificador del VAE para muestrear de la distribución aprendida. Utiliza el truco de reparametrización para permitir que los gradientes pasen a través de la capa.
  3. Definir una función de codificador: El modelo de codificador toma una entrada, la pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce dos vectores: un vector de medias (z_mean) y un vector de log varianza (z_log_var). La capa de Muestreo luego muestrea un punto de la distribución definida por estos vectores.
  4. Definir una función de decodificador: El modelo de decodificador toma un vector generado por el codificador, lo pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce un vector del mismo tamaño que los datos de entrada originales.
  5. Crear el modelo VAE: El modelo VAE se crea vinculando los modelos de codificador y decodificador.

El VAE puede usarse para generar nuevos datos similares a los datos de entrenamiento, lo que lo hace útil para tareas como eliminación de ruido, detección de anomalías y generación de datos.

5.1.3 Una Introducción al Entrenamiento del VAE

Entrenar el VAE implica minimizar la función de pérdida, que es una combinación de la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción puede medirse utilizando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo de los datos.

La pérdida de reconstrucción mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Si la reconstrucción es precisa, los datos reconstruidos coincidirán estrechamente con los datos originales, lo que lleva a una menor pérdida de reconstrucción. Por otro lado, si la reconstrucción es inexacta, los datos reconstruidos diferirán significativamente de los datos originales, lo que resultará en una mayor pérdida de reconstrucción. La pérdida de reconstrucción puede calcularse usando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo del tipo de datos.

La divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución previa (típicamente una Gaussiana estándar). Al minimizar la divergencia KL, se fomenta que el VAE no se desvíe drásticamente de nuestras suposiciones previas sobre el espacio latente.

El equilibrio entre reducir la pérdida de reconstrucción y minimizar la divergencia KL es lo que hace que entrenar un VAE sea una tarea compleja pero gratificante. Al optimizar estos dos componentes, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden utilizarse para diversas aplicaciones, empujando los límites de lo que es posible con el modelado generativo.

Función de Pérdida:
VAE Loss=Reconstruction Loss+KL Divergence

Ejemplo: Código de Entrenamiento

# Define the VAE loss
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = mse(inputs, outputs)
    reconstruction_loss *= input_shape[0]
    kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
    kl_loss = K.sum(kl_loss, axis=-1)
    kl_loss *= -0.5
    return K.mean(reconstruction_loss + kl_loss)

# Compile the VAE
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

# Load and preprocess the dataset (e.g., MNIST)
(x_train, _), (x_test, _) = tf.keras.datasets.mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((x_train.shape[0], np.prod(x_train.shape[1:])))
x_test = x_test.reshape((x_test.shape[0], np.prod(x_test.shape[1:])))

# Train the VAE
vae.fit(x_train, x_train, epochs=50, batch_size=128, validation_data=(x_test, x_test))

En este ejemplo:

La primera parte del código define la función de pérdida para el VAE. Esta función de pérdida es una combinación de dos componentes: la pérdida de reconstrucción y la divergencia de Kullback-Leibler (KL). La pérdida de reconstrucción se calcula utilizando el error cuadrático medio (mse) entre las entradas originales y las salidas reconstruidas. Esta pérdida mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Una pérdida de reconstrucción más baja indica que el modelo puede reconstruir eficazmente los datos de entrada, lo cual es una propiedad deseada en un buen autoencoder.

La divergencia KL, por otro lado, actúa como un término de regularización en la función de pérdida. Mide cuánto se desvía la distribución de las variables latentes aprendidas de una distribución normal estándar. La distribución normal estándar se usa a menudo como la distribución previa para las variables latentes en los VAEs debido a su simplicidad matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato. Al minimizar la divergencia KL, se anima al VAE a mantener la distribución latente aprendida cercana a la distribución previa.

Después de definir la función de pérdida, se compila el modelo VAE. Durante este paso, se utiliza el optimizador Adam, que es una elección popular para entrenar modelos de aprendizaje profundo porque combina las ventajas de dos otras extensiones del descenso de gradiente estocástico: AdaGrad y RMSProp. La función de pérdida utilizada para la compilación es la definida anteriormente, que toma como entradas las entradas originales, las salidas reconstruidas y los parámetros de la distribución latente aprendida.

La siguiente parte del código trata sobre la carga y el preprocesamiento del conjunto de datos. En este caso, se utiliza el conjunto de datos MNIST, que es una gran base de datos de dígitos escritos a mano que se usa comúnmente para entrenar varios sistemas de procesamiento de imágenes. Las imágenes se cargan, se normalizan para tener valores de píxeles entre 0 y 1, y se remodelan de matrices 2D a matrices 1D (o vectores), que es la forma de entrada requerida para el VAE.

Finalmente, el modelo VAE se entrena utilizando el conjunto de datos MNIST preprocesado. El modelo se entrena durante 50 épocas con un tamaño de lote de 128. Los mismos datos se utilizan tanto para la entrada como para el objetivo porque los VAEs son modelos de aprendizaje no supervisado que intentan recrear su entrada. Los datos de validación utilizados durante el entrenamiento son los datos de prueba del conjunto de datos MNIST.

Al ejecutar este código, puedes entrenar un VAE desde cero y comprender su funcionamiento interno. Sin embargo, ten en cuenta que el proceso de entrenamiento podría llevar un tiempo en completarse, especialmente si no estás utilizando una máquina potente o una GPU.

5.1.4 Muestreo del Espacio Latente

Una vez que el VAE está entrenado, podemos muestrear del espacio latente para generar nuevos datos. Esto implica muestrear variables latentes de la distribución previa (una distribución gaussiana estándar) y pasarlas a través del decodificador para generar nuevas muestras.

El proceso de generación de nuevos datos implica el muestreo del espacio latente. Esto se hace extrayendo variables latentes de la distribución previa, que suele ser una distribución gaussiana estándar. Esta distribución previa se elige debido a su conveniencia matemática y porque encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato.

Estas variables latentes muestreadas se pasan luego a través del componente decodificador del VAE. El decodificador es responsable de traducir las muestras extraídas de la distribución latente de vuelta al espacio de datos. Es durante este proceso que se generan nuevas muestras de datos. Estas nuevas muestras, en esencia, son una recreación basada en la representación condensada en el espacio latente.

Así, el proceso de generación de nuevos datos a partir del VAE implica una combinación de codificación de los datos de entrada en una distribución latente específica y luego la decodificación o traducción de muestras de esta distribución para generar nuevas muestras que sean similares a los datos originales.

Al aprovechar el poder de los Autoencoders Variacionales de esta manera, podemos crear una variedad de nuevas muestras de datos que imitan de cerca los datos de entrenamiento originales, y esto puede ser útil en una variedad de aplicaciones de ciencia de datos y aprendizaje automático.

Ejemplo: Código de Muestreo

import matplotlib.pyplot as plt
import numpy as np

# Generate new samples
def generate_samples(decoder, latent_dim, n_samples=10):
    random_latent_vectors = np.random.normal(size=(n_samples, latent_dim))
    generated_images = decoder.predict(random_latent_vectors)
    generated_images = generated_images.reshape((n_samples, 28, 28))
    return generated_images

# Plot generated samples
generated_images = generate_samples(decoder, latent_dim)
plt.figure(figsize=(10, 2))
for i in range(generated_images.shape[0]):
    plt.subplot(1, generated_images.shape[0], i + 1)
    plt.imshow(generated_images[i], cmap='gray')
    plt.axis('off')
plt.show()

En este ejemplo:

La función generate_samples(decoder, latent_dim, n_samples=10) genera una cantidad especificada de muestras (por defecto, 10) utilizando el modelo decodificador. El decodificador es uno de los dos componentes principales de un VAE (el otro es el codificador) y es responsable de generar nuevas muestras de datos a partir del espacio latente. El espacio latente es una representación de menor dimensión de los datos y es donde el VAE codifica las características clave de los datos.

La función comienza generando vectores latentes aleatorios a partir de una distribución normal. El tamaño de estos vectores está determinado por los parámetros n_samples y latent_dimn_samples es el número de muestras a generar y latent_dim es la dimensionalidad del espacio latente.

La línea decoder.predict(random_latent_vectors) utiliza el modelo decodificador para generar nuevas muestras de datos a partir de estos vectores latentes aleatorios. Estas muestras generadas se remodelan en imágenes con un formato de 28x28 píxeles, que es un tamaño común para las imágenes en conjuntos de datos como MNIST. Las imágenes remodeladas son devueltas por la función.

El siguiente bloque de código visualiza estas imágenes generadas en una sola fila utilizando Matplotlib. Crea una nueva figura, recorre las imágenes generadas y añade cada una a la figura como un subplot. Las imágenes se muestran en escala de grises, según lo especificado por cmap='gray', y las etiquetas de los ejes se desactivan con plt.axis('off'). Finalmente, se llama a plt.show() para mostrar la figura.

Este proceso de generar y visualizar nuevas muestras es una parte crucial del trabajo con VAEs y otros modelos generativos. Al visualizar las muestras generadas, podemos tener una idea de qué tan bien ha aprendido el modelo a imitar los datos de entrenamiento y si el espacio latente está estructurado de una manera útil.

Resumen

En la primera sección de este capítulo, profundizamos en los conceptos fundamentales y cruciales que subyacen a los Autoencoders Variacionales (VAEs), un tipo innovador y potente de modelo generativo. Nuestra exploración nos llevó a comprender la forma única en que los VAEs utilizan la inferencia variacional como un medio para aprender e internalizar una representación latente probabilística de los datos. Esto se logra combinando hábilmente las fortalezas de dos redes cruciales: un codificador y un decodificador.

Llevamos nuestra comprensión un paso más allá implementando prácticamente la arquitectura de los VAEs. Esto nos permitió comprender la mecánica y las sutilezas del modelo de una manera práctica. El conjunto de datos MNIST sirvió como la plataforma perfecta para este ejercicio, siendo un estándar en el campo para evaluar el rendimiento.

Además de implementar la arquitectura, también entrenamos el modelo en el conjunto de datos MNIST. Este proceso ilustró las capacidades de aprendizaje de los VAEs, ampliando nuestra comprensión de su potencial y limitaciones. Después del entrenamiento, demostramos el poder de los VAEs muestreando del espacio latente para generar nuevas imágenes no vistas. Esta aplicación práctica mostró la utilidad real de los VAEs y su potencial para crear nuevos datos realistas.

En conclusión, los VAEs son una herramienta increíblemente poderosa para la modelización generativa. Tienen la capacidad única de permitir la generación de una amplia gama de datos realistas y diversos. Al mismo tiempo, proporcionan representaciones latentes significativas, añadiendo otra capa de utilidad a su función. Con su combinación de utilidad práctica e intriga teórica, los VAEs ofrecen una vía prometedora para la exploración y el desarrollo futuro en el campo de la modelización generativa.

5.1 Entendiendo los VAEs

En este capítulo integral, nos embarcaremos en un viaje esclarecedor para descubrir el fascinante mundo de los Autoencoders Variacionales (VAEs). Los VAEs son una clase potente de modelos generativos que combinan hábilmente los principios de las redes neuronales y el modelado probabilístico, dando lugar a una herramienta computacional única con capacidades poderosas.

Lo que distingue a los VAEs es su capacidad inigualable para aprender representaciones latentes significativas y de alta calidad de los datos. Estas representaciones pueden ser aprovechadas para una multitud de propósitos, incluidos, pero no limitados a, generar nuevas muestras que imiten los datos de entrenamiento, comprimir los datos para un almacenamiento eficiente y diversas otras aplicaciones emocionantes que abarcan numerosos campos e industrias.

Nuestra inmersión profunda nos llevará a través de los fundamentos teóricos de los VAEs. Nos esforzaremos por comprender completamente su arquitectura compleja pero elegante, y cómo contribuye a su impresionante funcionalidad. Como una demostración práctica de la teoría, nos arremangaremos y gradualmente implementaremos un VAE desde cero. Esta experiencia práctica está diseñada para proporcionar una comprensión intuitiva de cómo interactúan los diferentes componentes para generar datos.

Para cuando termines este capítulo, no solo tendrás una comprensión sólida del funcionamiento interno de los VAEs, sino que también estarás equipado con el conocimiento práctico de cómo aplicarlos para abordar problemas del mundo real. Estarás listo para aprovechar el poder de los VAEs en tus propios proyectos de ciencia de datos, empujando los límites de lo que es posible con el modelado generativo.

Los Autoencoders Variacionales, también conocidos como VAEs, son un tipo único de modelo generativo. Estos modelos están diseñados con el objetivo específico de aprender a representar datos de manera efectiva y eficiente en un espacio latente de menor dimensión.

El espacio latente aquí es simplemente un constructo matemático que tiene la intención de condensar y capturar las características clave de los datos. Al representar los datos en esta forma más concentrada, se vuelve factible generar nuevas muestras de datos que tengan una notable similitud con los datos originales, esencialmente imitando las características clave de los datos originales.

Los VAEs se construyen a partir de dos componentes esenciales: el codificador y el decodificador. El codificador, como su nombre sugiere, es responsable de codificar, o mapear, los datos de entrada a una distribución latente específica. Esta distribución latente encapsula las características críticas de los datos en una forma compacta.

Por otro lado, el componente decodificador de los VAEs funciona en la dirección inversa. Mapea o traduce las muestras que se extraen de esta distribución latente de vuelta al espacio de datos. Este proceso implica esencialmente la generación de nuevas muestras de datos que son análogas a los datos originales, basándose en la representación condensada en el espacio latente. Así, a través de una combinación de procesos de codificación y decodificación, los VAEs pueden generar nuevas muestras de datos que son similares a los datos originales.

5.1.1 Fundamentos Teóricos

Los fundamentos teóricos de los Autoencoders Variacionales (VAEs) están enraizados en el concepto de inferencia variacional. Esta técnica se utiliza para aproximar distribuciones de probabilidad complejas.

A diferencia de los autoencoders tradicionales, que mapean los datos de entrada a un espacio latente determinista, los VAEs introducen un enfoque probabilístico a este proceso. En lugar de mapear cada entrada a un solo punto en el espacio latente, los VAEs mapean las entradas a una distribución sobre el espacio latente. Esta diferencia sutil permite a los VAEs capturar la incertidumbre y variabilidad inherentes en los datos, haciéndolos una herramienta potente para tareas como generar nuevas muestras que se asemejan a los datos de entrenamiento o comprimir datos para un almacenamiento eficiente.

El objetivo principal de un VAE es maximizar la probabilidad de los datos bajo el modelo. Esto esencialmente significa que el modelo busca encontrar la configuración más probable de parámetros que podría haber generado los datos observados. Simultáneamente, también asegura que el espacio latente se adhiera a una distribución conocida, típicamente una Gaussiana. Esta distribución conocida, referida como la prior, generalmente se elige por su conveniencia matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente incluso antes de observar cualquier dato.

Lograr este objetivo dual es posible mediante la optimización del Límite Inferior de la Evidencia (ELBO, por sus siglas en inglés), una cantidad derivada de los principios de la inferencia variacional. El ELBO consiste en dos términos: la Pérdida de Reconstrucción y la Divergencia KL.

La Pérdida de Reconstrucción es una medida de qué tan bien la parte decodificadora del VAE puede reconstruir los datos de entrada a partir de la representación latente. En esencia, cuantifica la discrepancia entre los datos originales y los datos regenerados desde el espacio latente, con una menor pérdida de reconstrucción indicando un mejor desempeño del VAE.

La Divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución prior (por ejemplo, una Gaussiana estándar). Al minimizar la Divergencia KL, el VAE se ve incentivado a no desviarse drásticamente de nuestras suposiciones previas sobre el espacio latente.

Al optimizar estos dos componentes del ELBO, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden ser utilizadas para una variedad de aplicaciones. Este equilibrio entre la fidelidad de los datos (a través de la pérdida de reconstrucción) y la adherencia a creencias previas (a través de la divergencia KL) es lo que hace a los VAEs una herramienta única y poderosa en el mundo del modelado generativo.

Matemáticamente:

ELBO=E
q(z∣x)

[logp(x∣z)]−KL(q(z∣x)∥p(z))

Donde:

  • ( q(z|x) ) es la aproximación del codificador de la distribución posterior.
  • ( p(x|z) ) es la verosimilitud del decodificador de los datos dados el variable latente.
  • ( p(z) ) es la distribución previa sobre los variables latentes, típicamente una distribución normal estándar.

5.1.2 Una Introducción a la Arquitectura de VAE

La arquitectura de un Autoencoder Variacional (VAE) consta de dos redes neuronales principales: el codificador y el decodificador. La función de la red del codificador es comprimir los datos de entrada, típicamente de alta dimensión, en una representación compacta en el espacio latente.

Este espacio latente, a menudo de menor dimensión, sirve como un cuello de botella que codifica las características esenciales de los datos de entrada. Posteriormente, entra en juego la red del decodificador. El decodificador toma la representación comprimida en el espacio latente y reconstruye los datos originales a partir de ella.

Esta reconstrucción es un intento de reflejar los datos de entrada originales lo más fielmente posible, permitiendo así que el VAE genere nuevos datos que compartan características similares con el conjunto de datos original.

Codificador:

El codificador juega un papel crucial en el proceso de entrenamiento del modelo. Su función principal es aceptar los datos de entrada, procesarlos y luego producir los parámetros que definen la distribución latente. Estos parámetros típicamente consisten en la media y la varianza.

Durante la fase de entrenamiento, las variables latentes, que son cruciales para los procesos de aprendizaje y predicción del modelo, se muestrean a partir de esta distribución. Este proceso de muestreo permite que el modelo genere un conjunto diverso de salidas y le ayuda a aprender la estructura subyacente de los datos de manera más efectiva.

Decodificador:

La función principal del decodificador es tomar las variables latentes muestreadas, que fueron extraídas y transformadas por el codificador, y procesarlas para generar los datos reconstruidos. Estos datos reconstruidos son una aproximación cercana a la entrada original.

El objetivo principal de este proceso es garantizar que se conserven las características clave de los datos de entrada, lo que permite al modelo lograr su objetivo de compresión de datos y reducción de ruido.

El codificador y el decodificador se entrenan simultáneamente para minimizar la pérdida de reconstrucción y la divergencia KL.

Ejemplo: Código de Arquitectura de VAE

Empecemos implementando la arquitectura de VAE usando TensorFlow y Keras:

import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Lambda, Layer
from tensorflow.keras.models import Model
from tensorflow.keras.losses import mse
from tensorflow.keras import backend as K

# Define the sampling layer
class Sampling(Layer):
    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon

# Encoder architecture
def build_encoder(input_shape, latent_dim):
    inputs = Input(shape=input_shape)
    x = Dense(512, activation='relu')(inputs)
    x = Dense(256, activation='relu')(x)
    z_mean = Dense(latent_dim, name='z_mean')(x)
    z_log_var = Dense(latent_dim, name='z_log_var')(x)
    z = Sampling()([z_mean, z_log_var])
    return Model(inputs, [z_mean, z_log_var, z], name='encoder')

# Decoder architecture
def build_decoder(latent_dim, output_shape):
    latent_inputs = Input(shape=(latent_dim,))
    x = Dense(256, activation='relu')(latent_inputs)
    x = Dense(512, activation='relu')(x)
    outputs = Dense(output_shape, activation='sigmoid')(x)
    return Model(latent_inputs, outputs, name='decoder')

# VAE architecture
input_shape = (784,)
latent_dim = 2

encoder = build_encoder(input_shape, latent_dim)
decoder = build_decoder(latent_dim, input_shape[0])

# Instantiate VAE
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')

El script se divide en las siguientes partes:

  1. Importar las bibliotecas necesarias: TensorFlow y Keras (una biblioteca de redes neuronales fácil de usar que se ejecuta sobre TensorFlow).
  2. Definir una capa de Muestreo (Sampling): Esta es una capa personalizada utilizada en el codificador del VAE para muestrear de la distribución aprendida. Utiliza el truco de reparametrización para permitir que los gradientes pasen a través de la capa.
  3. Definir una función de codificador: El modelo de codificador toma una entrada, la pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce dos vectores: un vector de medias (z_mean) y un vector de log varianza (z_log_var). La capa de Muestreo luego muestrea un punto de la distribución definida por estos vectores.
  4. Definir una función de decodificador: El modelo de decodificador toma un vector generado por el codificador, lo pasa a través de dos capas densas (cada una seguida por una función de activación ReLU) y produce un vector del mismo tamaño que los datos de entrada originales.
  5. Crear el modelo VAE: El modelo VAE se crea vinculando los modelos de codificador y decodificador.

El VAE puede usarse para generar nuevos datos similares a los datos de entrenamiento, lo que lo hace útil para tareas como eliminación de ruido, detección de anomalías y generación de datos.

5.1.3 Una Introducción al Entrenamiento del VAE

Entrenar el VAE implica minimizar la función de pérdida, que es una combinación de la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción puede medirse utilizando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo de los datos.

La pérdida de reconstrucción mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Si la reconstrucción es precisa, los datos reconstruidos coincidirán estrechamente con los datos originales, lo que lleva a una menor pérdida de reconstrucción. Por otro lado, si la reconstrucción es inexacta, los datos reconstruidos diferirán significativamente de los datos originales, lo que resultará en una mayor pérdida de reconstrucción. La pérdida de reconstrucción puede calcularse usando el error cuadrático medio (MSE) o la entropía cruzada binaria (BCE), dependiendo del tipo de datos.

La divergencia KL, por otro lado, actúa como un regularizador en el proceso de optimización. Asegura que la distribución latente aprendida esté cerca de la distribución previa (típicamente una Gaussiana estándar). Al minimizar la divergencia KL, se fomenta que el VAE no se desvíe drásticamente de nuestras suposiciones previas sobre el espacio latente.

El equilibrio entre reducir la pérdida de reconstrucción y minimizar la divergencia KL es lo que hace que entrenar un VAE sea una tarea compleja pero gratificante. Al optimizar estos dos componentes, los VAEs pueden aprender a generar representaciones latentes de alta calidad de los datos que pueden utilizarse para diversas aplicaciones, empujando los límites de lo que es posible con el modelado generativo.

Función de Pérdida:
VAE Loss=Reconstruction Loss+KL Divergence

Ejemplo: Código de Entrenamiento

# Define the VAE loss
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = mse(inputs, outputs)
    reconstruction_loss *= input_shape[0]
    kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
    kl_loss = K.sum(kl_loss, axis=-1)
    kl_loss *= -0.5
    return K.mean(reconstruction_loss + kl_loss)

# Compile the VAE
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

# Load and preprocess the dataset (e.g., MNIST)
(x_train, _), (x_test, _) = tf.keras.datasets.mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((x_train.shape[0], np.prod(x_train.shape[1:])))
x_test = x_test.reshape((x_test.shape[0], np.prod(x_test.shape[1:])))

# Train the VAE
vae.fit(x_train, x_train, epochs=50, batch_size=128, validation_data=(x_test, x_test))

En este ejemplo:

La primera parte del código define la función de pérdida para el VAE. Esta función de pérdida es una combinación de dos componentes: la pérdida de reconstrucción y la divergencia de Kullback-Leibler (KL). La pérdida de reconstrucción se calcula utilizando el error cuadrático medio (mse) entre las entradas originales y las salidas reconstruidas. Esta pérdida mide qué tan bien el modelo puede recrear los datos originales a partir de la representación latente. Una pérdida de reconstrucción más baja indica que el modelo puede reconstruir eficazmente los datos de entrada, lo cual es una propiedad deseada en un buen autoencoder.

La divergencia KL, por otro lado, actúa como un término de regularización en la función de pérdida. Mide cuánto se desvía la distribución de las variables latentes aprendidas de una distribución normal estándar. La distribución normal estándar se usa a menudo como la distribución previa para las variables latentes en los VAEs debido a su simplicidad matemática y la creencia de que encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato. Al minimizar la divergencia KL, se anima al VAE a mantener la distribución latente aprendida cercana a la distribución previa.

Después de definir la función de pérdida, se compila el modelo VAE. Durante este paso, se utiliza el optimizador Adam, que es una elección popular para entrenar modelos de aprendizaje profundo porque combina las ventajas de dos otras extensiones del descenso de gradiente estocástico: AdaGrad y RMSProp. La función de pérdida utilizada para la compilación es la definida anteriormente, que toma como entradas las entradas originales, las salidas reconstruidas y los parámetros de la distribución latente aprendida.

La siguiente parte del código trata sobre la carga y el preprocesamiento del conjunto de datos. En este caso, se utiliza el conjunto de datos MNIST, que es una gran base de datos de dígitos escritos a mano que se usa comúnmente para entrenar varios sistemas de procesamiento de imágenes. Las imágenes se cargan, se normalizan para tener valores de píxeles entre 0 y 1, y se remodelan de matrices 2D a matrices 1D (o vectores), que es la forma de entrada requerida para el VAE.

Finalmente, el modelo VAE se entrena utilizando el conjunto de datos MNIST preprocesado. El modelo se entrena durante 50 épocas con un tamaño de lote de 128. Los mismos datos se utilizan tanto para la entrada como para el objetivo porque los VAEs son modelos de aprendizaje no supervisado que intentan recrear su entrada. Los datos de validación utilizados durante el entrenamiento son los datos de prueba del conjunto de datos MNIST.

Al ejecutar este código, puedes entrenar un VAE desde cero y comprender su funcionamiento interno. Sin embargo, ten en cuenta que el proceso de entrenamiento podría llevar un tiempo en completarse, especialmente si no estás utilizando una máquina potente o una GPU.

5.1.4 Muestreo del Espacio Latente

Una vez que el VAE está entrenado, podemos muestrear del espacio latente para generar nuevos datos. Esto implica muestrear variables latentes de la distribución previa (una distribución gaussiana estándar) y pasarlas a través del decodificador para generar nuevas muestras.

El proceso de generación de nuevos datos implica el muestreo del espacio latente. Esto se hace extrayendo variables latentes de la distribución previa, que suele ser una distribución gaussiana estándar. Esta distribución previa se elige debido a su conveniencia matemática y porque encapsula nuestras suposiciones sobre la naturaleza del espacio latente antes de observar cualquier dato.

Estas variables latentes muestreadas se pasan luego a través del componente decodificador del VAE. El decodificador es responsable de traducir las muestras extraídas de la distribución latente de vuelta al espacio de datos. Es durante este proceso que se generan nuevas muestras de datos. Estas nuevas muestras, en esencia, son una recreación basada en la representación condensada en el espacio latente.

Así, el proceso de generación de nuevos datos a partir del VAE implica una combinación de codificación de los datos de entrada en una distribución latente específica y luego la decodificación o traducción de muestras de esta distribución para generar nuevas muestras que sean similares a los datos originales.

Al aprovechar el poder de los Autoencoders Variacionales de esta manera, podemos crear una variedad de nuevas muestras de datos que imitan de cerca los datos de entrenamiento originales, y esto puede ser útil en una variedad de aplicaciones de ciencia de datos y aprendizaje automático.

Ejemplo: Código de Muestreo

import matplotlib.pyplot as plt
import numpy as np

# Generate new samples
def generate_samples(decoder, latent_dim, n_samples=10):
    random_latent_vectors = np.random.normal(size=(n_samples, latent_dim))
    generated_images = decoder.predict(random_latent_vectors)
    generated_images = generated_images.reshape((n_samples, 28, 28))
    return generated_images

# Plot generated samples
generated_images = generate_samples(decoder, latent_dim)
plt.figure(figsize=(10, 2))
for i in range(generated_images.shape[0]):
    plt.subplot(1, generated_images.shape[0], i + 1)
    plt.imshow(generated_images[i], cmap='gray')
    plt.axis('off')
plt.show()

En este ejemplo:

La función generate_samples(decoder, latent_dim, n_samples=10) genera una cantidad especificada de muestras (por defecto, 10) utilizando el modelo decodificador. El decodificador es uno de los dos componentes principales de un VAE (el otro es el codificador) y es responsable de generar nuevas muestras de datos a partir del espacio latente. El espacio latente es una representación de menor dimensión de los datos y es donde el VAE codifica las características clave de los datos.

La función comienza generando vectores latentes aleatorios a partir de una distribución normal. El tamaño de estos vectores está determinado por los parámetros n_samples y latent_dimn_samples es el número de muestras a generar y latent_dim es la dimensionalidad del espacio latente.

La línea decoder.predict(random_latent_vectors) utiliza el modelo decodificador para generar nuevas muestras de datos a partir de estos vectores latentes aleatorios. Estas muestras generadas se remodelan en imágenes con un formato de 28x28 píxeles, que es un tamaño común para las imágenes en conjuntos de datos como MNIST. Las imágenes remodeladas son devueltas por la función.

El siguiente bloque de código visualiza estas imágenes generadas en una sola fila utilizando Matplotlib. Crea una nueva figura, recorre las imágenes generadas y añade cada una a la figura como un subplot. Las imágenes se muestran en escala de grises, según lo especificado por cmap='gray', y las etiquetas de los ejes se desactivan con plt.axis('off'). Finalmente, se llama a plt.show() para mostrar la figura.

Este proceso de generar y visualizar nuevas muestras es una parte crucial del trabajo con VAEs y otros modelos generativos. Al visualizar las muestras generadas, podemos tener una idea de qué tan bien ha aprendido el modelo a imitar los datos de entrenamiento y si el espacio latente está estructurado de una manera útil.

Resumen

En la primera sección de este capítulo, profundizamos en los conceptos fundamentales y cruciales que subyacen a los Autoencoders Variacionales (VAEs), un tipo innovador y potente de modelo generativo. Nuestra exploración nos llevó a comprender la forma única en que los VAEs utilizan la inferencia variacional como un medio para aprender e internalizar una representación latente probabilística de los datos. Esto se logra combinando hábilmente las fortalezas de dos redes cruciales: un codificador y un decodificador.

Llevamos nuestra comprensión un paso más allá implementando prácticamente la arquitectura de los VAEs. Esto nos permitió comprender la mecánica y las sutilezas del modelo de una manera práctica. El conjunto de datos MNIST sirvió como la plataforma perfecta para este ejercicio, siendo un estándar en el campo para evaluar el rendimiento.

Además de implementar la arquitectura, también entrenamos el modelo en el conjunto de datos MNIST. Este proceso ilustró las capacidades de aprendizaje de los VAEs, ampliando nuestra comprensión de su potencial y limitaciones. Después del entrenamiento, demostramos el poder de los VAEs muestreando del espacio latente para generar nuevas imágenes no vistas. Esta aplicación práctica mostró la utilidad real de los VAEs y su potencial para crear nuevos datos realistas.

En conclusión, los VAEs son una herramienta increíblemente poderosa para la modelización generativa. Tienen la capacidad única de permitir la generación de una amplia gama de datos realistas y diversos. Al mismo tiempo, proporcionan representaciones latentes significativas, añadiendo otra capa de utilidad a su función. Con su combinación de utilidad práctica e intriga teórica, los VAEs ofrecen una vía prometedora para la exploración y el desarrollo futuro en el campo de la modelización generativa.