Menu iconMenu icon
Generative Deep Learning Edición Actualizada

Capítulo 6: Proyecto: Generación de Dígitos Manuscritos con VAEs

6.2 Creación del Modelo

En esta sección, nos enfocaremos en la creación del modelo de Autoencoder Variacional (VAE) para generar dígitos manuscritos. El modelo consta de dos componentes principales: el codificador y el decodificador. El codificador mapea las imágenes de entrada a un espacio latente, mientras que el decodificador reconstruye las imágenes desde el espacio latente. También implementaremos el truco de reparametrización para asegurar que el modelo se pueda entrenar de manera efectiva usando descenso de gradiente.

6.2.1 Definiendo el Codificador

El codificador comprime los datos de entrada en un espacio latente de menor dimensión. Produce los parámetros de la distribución latente, típicamente la media y la varianza logarítmica.

Componentes Clave:

  • Capa de Entrada: Recibe los datos de imagen originales.
  • Capas Densas: Procesan los datos de entrada.
  • Variables Latentes: Producen la media y la varianza logarítmica de la distribución latente.

Ejemplo: Implementación del Codificador

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

# Define the sampling layer using the reparameterization trick
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 = K.random_normal(shape=(batch, dim))
        return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Build the encoder network
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')

# Define the input shape and latent dimension
input_shape = (784,)
latent_dim = 2

# Build the encoder
encoder = build_encoder(input_shape, latent_dim)
encoder.summary()

Este código de ejemplo utiliza la biblioteca TensorFlow para crear la parte del codificador de un Autoencoder Variacional (VAE). Define una capa de muestreo (Sampling), que utiliza el truco de reparametrización para permitir la retropropagación a través de la operación de muestreo aleatorio.

La red del codificador se construye con capas densas y genera dos salidas, z_mean y z_log_var, que representan los parámetros de la distribución del espacio latente. La capa de muestreo (Sampling) luego utiliza estos parámetros para muestrear un punto en el espacio latente. El modelo del codificador se construye finalmente utilizando la forma de entrada definida y la dimensión latente.

6.2.2 Definiendo el Decodificador

El decodificador reconstruye los datos de entrada a partir de las variables latentes. Mapea el espacio latente de vuelta al espacio de datos, generando nuevas imágenes que se asemejan a la entrada original.

Componentes Clave:

  • Entrada Latente: Recibe las variables latentes muestreadas.
  • Capas Densas: Transforman las variables latentes en los datos de salida.
  • Capa de Salida: Genera las imágenes reconstruidas, típicamente utilizando una activación sigmoide para los valores de píxeles en el rango [0, 1].

Ejemplo: Implementación del Decodificador

# Build the decoder network
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')

# Build the decoder
decoder = build_decoder(latent_dim, input_shape[0])
decoder.summary()

La red del decodificador se construye utilizando la API funcional de Keras. Comienza con una capa de entrada que recibe datos de forma latent_dim. Esto es seguido por dos capas densas (o completamente conectadas) con 256 y 512 neuronas respectivamente, cada una utilizando la función de activación ReLU (Unidad Lineal Rectificada). La capa final es otra capa densa con neuronas de output_shape y utiliza la función de activación sigmoide.

Después de definir esta estructura de red del decodificador en la función build_decoder, se construye una instancia del decodificador y se imprime su resumen (una visión concisa de las capas y parámetros de la red).

6.2.3 Combinando el Codificador y el Decodificador

A continuación, combinaremos el codificador y el decodificador para crear el modelo VAE. El VAE toma una imagen de entrada, la codifica en el espacio latente y luego la decodifica nuevamente en una imagen. El VAE se entrena para minimizar la pérdida de reconstrucción y la divergencia KL.

Arquitectura del VAE:

  • Entradas: Datos de imagen originales.
  • Codificador: Comprime los datos de entrada en variables latentes.
  • Decodificador: Reconstruye los datos de entrada a partir de las variables latentes.
  • Salidas: Imágenes reconstruidas.

Ejemplo: Implementación del Modelo VAE

# Define the VAE model
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')
vae.summary()

Este código comienza definiendo la forma de entrada, luego crea la parte del codificador del modelo que toma la entrada y produce la media, la varianza logarítmica y un vector latente 'z'. Luego, la parte del decodificador del modelo toma el vector latente 'z' y produce la salida. Estos componentes se combinan para formar el modelo VAE en su conjunto. La última línea del código muestra el resumen del modelo.

6.2.4 Definiendo la Función de Pérdida

La función de pérdida para los VAEs combina la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción mide qué tan bien el decodificador puede reconstruir los datos de entrada, mientras que la divergencia KL mide la diferencia entre la distribución latente aprendida y la distribución previa (usualmente una distribución normal estándar).

Función de Pérdida:

VAE Loss=Reconstruction Loss+KL Divergence

Pérdida de Reconstrucción:
A menudo se mide usando la Entropía Cruzada Binaria (BCE) cuando los datos de entrada están normalizados en el rango [0, 1].

Divergencia KL:
Mide la diferencia entre la distribución aprendida y la distribución previa.

Ejemplo: Implementación de la Función de Pérdida

# Define the VAE loss function
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = tf.keras.losses.binary_crossentropy(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 model
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

La función 'vae_loss' calcula tanto la pérdida de reconstrucción como la pérdida de divergencia KL.

  • La 'pérdida de reconstrucción' mide qué tan bien el VAE puede reproducir los datos de entrada después de codificarlos y decodificarlos. Utiliza la entropía cruzada binaria como la medida de diferencia entre las entradas originales y las reconstruidas.
  • La 'pérdida de divergencia KL' mide cuánto se desvía la distribución de variables latentes aprendida de la distribución previa (que en este caso es una distribución normal estándar).

El modelo VAE se compila luego con el optimizador Adam y la función de pérdida definida.

6.2.5 Entrenando el VAE

Entrenar el VAE implica minimizar la función de pérdida combinada utilizando el descenso de gradiente. Usaremos el conjunto de datos MNIST para entrenar el VAE y monitorear el proceso de entrenamiento para asegurarnos de que el modelo aprenda de manera efectiva.

Ejemplo: Entrenando el VAE

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

La función fit se está utilizando para entrenar el modelo durante 50 épocas (iteraciones sobre todo el conjunto de datos) con un tamaño de lote de 128 (el número de muestras por actualización de gradiente). Se está utilizando el mismo conjunto de datos tanto como entrada como objetivo, lo cual es típico para los autoencoders. El rendimiento del modelo se está validando usando un conjunto de datos de prueba separado.

Resumen

En esta sección, creamos exitosamente el modelo de Autoencoder Variacional (VAE) para generar dígitos escritos a mano. Definimos las redes del codificador y decodificador, las combinamos para formar el VAE, e implementamos el truco de reparametrización. También definimos la función de pérdida del VAE, que combina la pérdida de reconstrucción y la divergencia KL, y entrenamos el modelo utilizando el conjunto de datos MNIST.

Con el modelo VAE entrenado, estamos listos para pasar al siguiente paso: generar nuevos dígitos escritos a mano.

6.2 Creación del Modelo

En esta sección, nos enfocaremos en la creación del modelo de Autoencoder Variacional (VAE) para generar dígitos manuscritos. El modelo consta de dos componentes principales: el codificador y el decodificador. El codificador mapea las imágenes de entrada a un espacio latente, mientras que el decodificador reconstruye las imágenes desde el espacio latente. También implementaremos el truco de reparametrización para asegurar que el modelo se pueda entrenar de manera efectiva usando descenso de gradiente.

6.2.1 Definiendo el Codificador

El codificador comprime los datos de entrada en un espacio latente de menor dimensión. Produce los parámetros de la distribución latente, típicamente la media y la varianza logarítmica.

Componentes Clave:

  • Capa de Entrada: Recibe los datos de imagen originales.
  • Capas Densas: Procesan los datos de entrada.
  • Variables Latentes: Producen la media y la varianza logarítmica de la distribución latente.

Ejemplo: Implementación del Codificador

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

# Define the sampling layer using the reparameterization trick
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 = K.random_normal(shape=(batch, dim))
        return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Build the encoder network
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')

# Define the input shape and latent dimension
input_shape = (784,)
latent_dim = 2

# Build the encoder
encoder = build_encoder(input_shape, latent_dim)
encoder.summary()

Este código de ejemplo utiliza la biblioteca TensorFlow para crear la parte del codificador de un Autoencoder Variacional (VAE). Define una capa de muestreo (Sampling), que utiliza el truco de reparametrización para permitir la retropropagación a través de la operación de muestreo aleatorio.

La red del codificador se construye con capas densas y genera dos salidas, z_mean y z_log_var, que representan los parámetros de la distribución del espacio latente. La capa de muestreo (Sampling) luego utiliza estos parámetros para muestrear un punto en el espacio latente. El modelo del codificador se construye finalmente utilizando la forma de entrada definida y la dimensión latente.

6.2.2 Definiendo el Decodificador

El decodificador reconstruye los datos de entrada a partir de las variables latentes. Mapea el espacio latente de vuelta al espacio de datos, generando nuevas imágenes que se asemejan a la entrada original.

Componentes Clave:

  • Entrada Latente: Recibe las variables latentes muestreadas.
  • Capas Densas: Transforman las variables latentes en los datos de salida.
  • Capa de Salida: Genera las imágenes reconstruidas, típicamente utilizando una activación sigmoide para los valores de píxeles en el rango [0, 1].

Ejemplo: Implementación del Decodificador

# Build the decoder network
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')

# Build the decoder
decoder = build_decoder(latent_dim, input_shape[0])
decoder.summary()

La red del decodificador se construye utilizando la API funcional de Keras. Comienza con una capa de entrada que recibe datos de forma latent_dim. Esto es seguido por dos capas densas (o completamente conectadas) con 256 y 512 neuronas respectivamente, cada una utilizando la función de activación ReLU (Unidad Lineal Rectificada). La capa final es otra capa densa con neuronas de output_shape y utiliza la función de activación sigmoide.

Después de definir esta estructura de red del decodificador en la función build_decoder, se construye una instancia del decodificador y se imprime su resumen (una visión concisa de las capas y parámetros de la red).

6.2.3 Combinando el Codificador y el Decodificador

A continuación, combinaremos el codificador y el decodificador para crear el modelo VAE. El VAE toma una imagen de entrada, la codifica en el espacio latente y luego la decodifica nuevamente en una imagen. El VAE se entrena para minimizar la pérdida de reconstrucción y la divergencia KL.

Arquitectura del VAE:

  • Entradas: Datos de imagen originales.
  • Codificador: Comprime los datos de entrada en variables latentes.
  • Decodificador: Reconstruye los datos de entrada a partir de las variables latentes.
  • Salidas: Imágenes reconstruidas.

Ejemplo: Implementación del Modelo VAE

# Define the VAE model
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')
vae.summary()

Este código comienza definiendo la forma de entrada, luego crea la parte del codificador del modelo que toma la entrada y produce la media, la varianza logarítmica y un vector latente 'z'. Luego, la parte del decodificador del modelo toma el vector latente 'z' y produce la salida. Estos componentes se combinan para formar el modelo VAE en su conjunto. La última línea del código muestra el resumen del modelo.

6.2.4 Definiendo la Función de Pérdida

La función de pérdida para los VAEs combina la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción mide qué tan bien el decodificador puede reconstruir los datos de entrada, mientras que la divergencia KL mide la diferencia entre la distribución latente aprendida y la distribución previa (usualmente una distribución normal estándar).

Función de Pérdida:

VAE Loss=Reconstruction Loss+KL Divergence

Pérdida de Reconstrucción:
A menudo se mide usando la Entropía Cruzada Binaria (BCE) cuando los datos de entrada están normalizados en el rango [0, 1].

Divergencia KL:
Mide la diferencia entre la distribución aprendida y la distribución previa.

Ejemplo: Implementación de la Función de Pérdida

# Define the VAE loss function
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = tf.keras.losses.binary_crossentropy(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 model
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

La función 'vae_loss' calcula tanto la pérdida de reconstrucción como la pérdida de divergencia KL.

  • La 'pérdida de reconstrucción' mide qué tan bien el VAE puede reproducir los datos de entrada después de codificarlos y decodificarlos. Utiliza la entropía cruzada binaria como la medida de diferencia entre las entradas originales y las reconstruidas.
  • La 'pérdida de divergencia KL' mide cuánto se desvía la distribución de variables latentes aprendida de la distribución previa (que en este caso es una distribución normal estándar).

El modelo VAE se compila luego con el optimizador Adam y la función de pérdida definida.

6.2.5 Entrenando el VAE

Entrenar el VAE implica minimizar la función de pérdida combinada utilizando el descenso de gradiente. Usaremos el conjunto de datos MNIST para entrenar el VAE y monitorear el proceso de entrenamiento para asegurarnos de que el modelo aprenda de manera efectiva.

Ejemplo: Entrenando el VAE

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

La función fit se está utilizando para entrenar el modelo durante 50 épocas (iteraciones sobre todo el conjunto de datos) con un tamaño de lote de 128 (el número de muestras por actualización de gradiente). Se está utilizando el mismo conjunto de datos tanto como entrada como objetivo, lo cual es típico para los autoencoders. El rendimiento del modelo se está validando usando un conjunto de datos de prueba separado.

Resumen

En esta sección, creamos exitosamente el modelo de Autoencoder Variacional (VAE) para generar dígitos escritos a mano. Definimos las redes del codificador y decodificador, las combinamos para formar el VAE, e implementamos el truco de reparametrización. También definimos la función de pérdida del VAE, que combina la pérdida de reconstrucción y la divergencia KL, y entrenamos el modelo utilizando el conjunto de datos MNIST.

Con el modelo VAE entrenado, estamos listos para pasar al siguiente paso: generar nuevos dígitos escritos a mano.

6.2 Creación del Modelo

En esta sección, nos enfocaremos en la creación del modelo de Autoencoder Variacional (VAE) para generar dígitos manuscritos. El modelo consta de dos componentes principales: el codificador y el decodificador. El codificador mapea las imágenes de entrada a un espacio latente, mientras que el decodificador reconstruye las imágenes desde el espacio latente. También implementaremos el truco de reparametrización para asegurar que el modelo se pueda entrenar de manera efectiva usando descenso de gradiente.

6.2.1 Definiendo el Codificador

El codificador comprime los datos de entrada en un espacio latente de menor dimensión. Produce los parámetros de la distribución latente, típicamente la media y la varianza logarítmica.

Componentes Clave:

  • Capa de Entrada: Recibe los datos de imagen originales.
  • Capas Densas: Procesan los datos de entrada.
  • Variables Latentes: Producen la media y la varianza logarítmica de la distribución latente.

Ejemplo: Implementación del Codificador

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

# Define the sampling layer using the reparameterization trick
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 = K.random_normal(shape=(batch, dim))
        return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Build the encoder network
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')

# Define the input shape and latent dimension
input_shape = (784,)
latent_dim = 2

# Build the encoder
encoder = build_encoder(input_shape, latent_dim)
encoder.summary()

Este código de ejemplo utiliza la biblioteca TensorFlow para crear la parte del codificador de un Autoencoder Variacional (VAE). Define una capa de muestreo (Sampling), que utiliza el truco de reparametrización para permitir la retropropagación a través de la operación de muestreo aleatorio.

La red del codificador se construye con capas densas y genera dos salidas, z_mean y z_log_var, que representan los parámetros de la distribución del espacio latente. La capa de muestreo (Sampling) luego utiliza estos parámetros para muestrear un punto en el espacio latente. El modelo del codificador se construye finalmente utilizando la forma de entrada definida y la dimensión latente.

6.2.2 Definiendo el Decodificador

El decodificador reconstruye los datos de entrada a partir de las variables latentes. Mapea el espacio latente de vuelta al espacio de datos, generando nuevas imágenes que se asemejan a la entrada original.

Componentes Clave:

  • Entrada Latente: Recibe las variables latentes muestreadas.
  • Capas Densas: Transforman las variables latentes en los datos de salida.
  • Capa de Salida: Genera las imágenes reconstruidas, típicamente utilizando una activación sigmoide para los valores de píxeles en el rango [0, 1].

Ejemplo: Implementación del Decodificador

# Build the decoder network
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')

# Build the decoder
decoder = build_decoder(latent_dim, input_shape[0])
decoder.summary()

La red del decodificador se construye utilizando la API funcional de Keras. Comienza con una capa de entrada que recibe datos de forma latent_dim. Esto es seguido por dos capas densas (o completamente conectadas) con 256 y 512 neuronas respectivamente, cada una utilizando la función de activación ReLU (Unidad Lineal Rectificada). La capa final es otra capa densa con neuronas de output_shape y utiliza la función de activación sigmoide.

Después de definir esta estructura de red del decodificador en la función build_decoder, se construye una instancia del decodificador y se imprime su resumen (una visión concisa de las capas y parámetros de la red).

6.2.3 Combinando el Codificador y el Decodificador

A continuación, combinaremos el codificador y el decodificador para crear el modelo VAE. El VAE toma una imagen de entrada, la codifica en el espacio latente y luego la decodifica nuevamente en una imagen. El VAE se entrena para minimizar la pérdida de reconstrucción y la divergencia KL.

Arquitectura del VAE:

  • Entradas: Datos de imagen originales.
  • Codificador: Comprime los datos de entrada en variables latentes.
  • Decodificador: Reconstruye los datos de entrada a partir de las variables latentes.
  • Salidas: Imágenes reconstruidas.

Ejemplo: Implementación del Modelo VAE

# Define the VAE model
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')
vae.summary()

Este código comienza definiendo la forma de entrada, luego crea la parte del codificador del modelo que toma la entrada y produce la media, la varianza logarítmica y un vector latente 'z'. Luego, la parte del decodificador del modelo toma el vector latente 'z' y produce la salida. Estos componentes se combinan para formar el modelo VAE en su conjunto. La última línea del código muestra el resumen del modelo.

6.2.4 Definiendo la Función de Pérdida

La función de pérdida para los VAEs combina la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción mide qué tan bien el decodificador puede reconstruir los datos de entrada, mientras que la divergencia KL mide la diferencia entre la distribución latente aprendida y la distribución previa (usualmente una distribución normal estándar).

Función de Pérdida:

VAE Loss=Reconstruction Loss+KL Divergence

Pérdida de Reconstrucción:
A menudo se mide usando la Entropía Cruzada Binaria (BCE) cuando los datos de entrada están normalizados en el rango [0, 1].

Divergencia KL:
Mide la diferencia entre la distribución aprendida y la distribución previa.

Ejemplo: Implementación de la Función de Pérdida

# Define the VAE loss function
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = tf.keras.losses.binary_crossentropy(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 model
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

La función 'vae_loss' calcula tanto la pérdida de reconstrucción como la pérdida de divergencia KL.

  • La 'pérdida de reconstrucción' mide qué tan bien el VAE puede reproducir los datos de entrada después de codificarlos y decodificarlos. Utiliza la entropía cruzada binaria como la medida de diferencia entre las entradas originales y las reconstruidas.
  • La 'pérdida de divergencia KL' mide cuánto se desvía la distribución de variables latentes aprendida de la distribución previa (que en este caso es una distribución normal estándar).

El modelo VAE se compila luego con el optimizador Adam y la función de pérdida definida.

6.2.5 Entrenando el VAE

Entrenar el VAE implica minimizar la función de pérdida combinada utilizando el descenso de gradiente. Usaremos el conjunto de datos MNIST para entrenar el VAE y monitorear el proceso de entrenamiento para asegurarnos de que el modelo aprenda de manera efectiva.

Ejemplo: Entrenando el VAE

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

La función fit se está utilizando para entrenar el modelo durante 50 épocas (iteraciones sobre todo el conjunto de datos) con un tamaño de lote de 128 (el número de muestras por actualización de gradiente). Se está utilizando el mismo conjunto de datos tanto como entrada como objetivo, lo cual es típico para los autoencoders. El rendimiento del modelo se está validando usando un conjunto de datos de prueba separado.

Resumen

En esta sección, creamos exitosamente el modelo de Autoencoder Variacional (VAE) para generar dígitos escritos a mano. Definimos las redes del codificador y decodificador, las combinamos para formar el VAE, e implementamos el truco de reparametrización. También definimos la función de pérdida del VAE, que combina la pérdida de reconstrucción y la divergencia KL, y entrenamos el modelo utilizando el conjunto de datos MNIST.

Con el modelo VAE entrenado, estamos listos para pasar al siguiente paso: generar nuevos dígitos escritos a mano.

6.2 Creación del Modelo

En esta sección, nos enfocaremos en la creación del modelo de Autoencoder Variacional (VAE) para generar dígitos manuscritos. El modelo consta de dos componentes principales: el codificador y el decodificador. El codificador mapea las imágenes de entrada a un espacio latente, mientras que el decodificador reconstruye las imágenes desde el espacio latente. También implementaremos el truco de reparametrización para asegurar que el modelo se pueda entrenar de manera efectiva usando descenso de gradiente.

6.2.1 Definiendo el Codificador

El codificador comprime los datos de entrada en un espacio latente de menor dimensión. Produce los parámetros de la distribución latente, típicamente la media y la varianza logarítmica.

Componentes Clave:

  • Capa de Entrada: Recibe los datos de imagen originales.
  • Capas Densas: Procesan los datos de entrada.
  • Variables Latentes: Producen la media y la varianza logarítmica de la distribución latente.

Ejemplo: Implementación del Codificador

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

# Define the sampling layer using the reparameterization trick
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 = K.random_normal(shape=(batch, dim))
        return z_mean + K.exp(0.5 * z_log_var) * epsilon

# Build the encoder network
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')

# Define the input shape and latent dimension
input_shape = (784,)
latent_dim = 2

# Build the encoder
encoder = build_encoder(input_shape, latent_dim)
encoder.summary()

Este código de ejemplo utiliza la biblioteca TensorFlow para crear la parte del codificador de un Autoencoder Variacional (VAE). Define una capa de muestreo (Sampling), que utiliza el truco de reparametrización para permitir la retropropagación a través de la operación de muestreo aleatorio.

La red del codificador se construye con capas densas y genera dos salidas, z_mean y z_log_var, que representan los parámetros de la distribución del espacio latente. La capa de muestreo (Sampling) luego utiliza estos parámetros para muestrear un punto en el espacio latente. El modelo del codificador se construye finalmente utilizando la forma de entrada definida y la dimensión latente.

6.2.2 Definiendo el Decodificador

El decodificador reconstruye los datos de entrada a partir de las variables latentes. Mapea el espacio latente de vuelta al espacio de datos, generando nuevas imágenes que se asemejan a la entrada original.

Componentes Clave:

  • Entrada Latente: Recibe las variables latentes muestreadas.
  • Capas Densas: Transforman las variables latentes en los datos de salida.
  • Capa de Salida: Genera las imágenes reconstruidas, típicamente utilizando una activación sigmoide para los valores de píxeles en el rango [0, 1].

Ejemplo: Implementación del Decodificador

# Build the decoder network
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')

# Build the decoder
decoder = build_decoder(latent_dim, input_shape[0])
decoder.summary()

La red del decodificador se construye utilizando la API funcional de Keras. Comienza con una capa de entrada que recibe datos de forma latent_dim. Esto es seguido por dos capas densas (o completamente conectadas) con 256 y 512 neuronas respectivamente, cada una utilizando la función de activación ReLU (Unidad Lineal Rectificada). La capa final es otra capa densa con neuronas de output_shape y utiliza la función de activación sigmoide.

Después de definir esta estructura de red del decodificador en la función build_decoder, se construye una instancia del decodificador y se imprime su resumen (una visión concisa de las capas y parámetros de la red).

6.2.3 Combinando el Codificador y el Decodificador

A continuación, combinaremos el codificador y el decodificador para crear el modelo VAE. El VAE toma una imagen de entrada, la codifica en el espacio latente y luego la decodifica nuevamente en una imagen. El VAE se entrena para minimizar la pérdida de reconstrucción y la divergencia KL.

Arquitectura del VAE:

  • Entradas: Datos de imagen originales.
  • Codificador: Comprime los datos de entrada en variables latentes.
  • Decodificador: Reconstruye los datos de entrada a partir de las variables latentes.
  • Salidas: Imágenes reconstruidas.

Ejemplo: Implementación del Modelo VAE

# Define the VAE model
inputs = Input(shape=input_shape)
z_mean, z_log_var, z = encoder(inputs)
outputs = decoder(z)
vae = Model(inputs, outputs, name='vae')
vae.summary()

Este código comienza definiendo la forma de entrada, luego crea la parte del codificador del modelo que toma la entrada y produce la media, la varianza logarítmica y un vector latente 'z'. Luego, la parte del decodificador del modelo toma el vector latente 'z' y produce la salida. Estos componentes se combinan para formar el modelo VAE en su conjunto. La última línea del código muestra el resumen del modelo.

6.2.4 Definiendo la Función de Pérdida

La función de pérdida para los VAEs combina la pérdida de reconstrucción y la divergencia KL. La pérdida de reconstrucción mide qué tan bien el decodificador puede reconstruir los datos de entrada, mientras que la divergencia KL mide la diferencia entre la distribución latente aprendida y la distribución previa (usualmente una distribución normal estándar).

Función de Pérdida:

VAE Loss=Reconstruction Loss+KL Divergence

Pérdida de Reconstrucción:
A menudo se mide usando la Entropía Cruzada Binaria (BCE) cuando los datos de entrada están normalizados en el rango [0, 1].

Divergencia KL:
Mide la diferencia entre la distribución aprendida y la distribución previa.

Ejemplo: Implementación de la Función de Pérdida

# Define the VAE loss function
def vae_loss(inputs, outputs, z_mean, z_log_var):
    reconstruction_loss = tf.keras.losses.binary_crossentropy(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 model
vae.compile(optimizer='adam', loss=lambda x, y: vae_loss(x, y, z_mean, z_log_var))

La función 'vae_loss' calcula tanto la pérdida de reconstrucción como la pérdida de divergencia KL.

  • La 'pérdida de reconstrucción' mide qué tan bien el VAE puede reproducir los datos de entrada después de codificarlos y decodificarlos. Utiliza la entropía cruzada binaria como la medida de diferencia entre las entradas originales y las reconstruidas.
  • La 'pérdida de divergencia KL' mide cuánto se desvía la distribución de variables latentes aprendida de la distribución previa (que en este caso es una distribución normal estándar).

El modelo VAE se compila luego con el optimizador Adam y la función de pérdida definida.

6.2.5 Entrenando el VAE

Entrenar el VAE implica minimizar la función de pérdida combinada utilizando el descenso de gradiente. Usaremos el conjunto de datos MNIST para entrenar el VAE y monitorear el proceso de entrenamiento para asegurarnos de que el modelo aprenda de manera efectiva.

Ejemplo: Entrenando el VAE

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

La función fit se está utilizando para entrenar el modelo durante 50 épocas (iteraciones sobre todo el conjunto de datos) con un tamaño de lote de 128 (el número de muestras por actualización de gradiente). Se está utilizando el mismo conjunto de datos tanto como entrada como objetivo, lo cual es típico para los autoencoders. El rendimiento del modelo se está validando usando un conjunto de datos de prueba separado.

Resumen

En esta sección, creamos exitosamente el modelo de Autoencoder Variacional (VAE) para generar dígitos escritos a mano. Definimos las redes del codificador y decodificador, las combinamos para formar el VAE, e implementamos el truco de reparametrización. También definimos la función de pérdida del VAE, que combina la pérdida de reconstrucción y la divergencia KL, y entrenamos el modelo utilizando el conjunto de datos MNIST.

Con el modelo VAE entrenado, estamos listos para pasar al siguiente paso: generar nuevos dígitos escritos a mano.