Image for post Guía Completa para Crear Tu Primer Modelo Generativo con Redes Generativas Antagónicas (GANs) para Principiantes

Guía Completa para Crear Tu Primer Modelo Generativo con Redes Generativas Antagónicas (GANs) para Principiantes


Las Redes Generativas Antagónicas, conocidas como GANs, revolucionaron el campo de la inteligencia artificial gracias a su capacidad para generar datos sintéticos realistas, desde imágenes hasta audio y texto. En esta guía para principiantes, exploraremos su concepto central, entenderemos cómo funcionan y construiremos un ejemplo básico de GAN en Python utilizando la biblioteca TensorFlow.

¿Qué es una Red Generativa Antagónica (GAN)?

Las GANs son una clase de modelos de machine learning compuestos por dos redes neuronales que compiten entre sí:

  • Generador (Generator): Trata de crear datos sintéticos que imiten a los datos reales.
  • Discriminador (Discriminator): Evalúa si una muestra proviene del conjunto de datos real o del generador.

Esta estructura de competencia adversarial lleva al generador a mejorar progresivamente hasta producir datos casi indistinguibles de los reales.

¿Cómo funciona una GAN? Explicación sencilla

  1. El generador crea datos falsos a partir de ruido aleatorio.
  2. El discriminador recibe datos reales y datos falsos y debe clasificarlos correctamente.
  3. Se calculan pérdidas para ambos modelos: el generador busca engañar al discriminador y el discriminador busca no dejarse engañar.
  4. Ambos modelos se entrenan simultáneamente en un juego de suma cero hasta que el generador produce datos convincentes.

Aplicaciones comunes de las GANs

  • Generación de imágenes realistas (caras, paisajes).
  • Aumento de datos para entrenamiento de modelos.
  • Restauración y mejora de imágenes (superresolución).
  • Creación de arte y diseño automático.
  • Síntesis de voz y audio.

Ejemplo Práctico: Entrenando una GAN para crear dígitos manuscritos

Utilizaremos el dataset MNIST, que contiene imágenes de dígitos escritos a mano. La idea es que la GAN aprenda a generar imágenes similares.

Preparando el entorno

Necesitaremos TensorFlow y Matplotlib. Puedes instalarlo con:

pip install tensorflow matplotlib

Código básico de la GAN

import tensorflow as tf
from tensorflow.keras import layers
import numpy as np
import matplotlib.pyplot as plt

def make_generator_model():
    model = tf.keras.Sequential([
        layers.Dense(7*7*256, use_bias=False, input_shape=(100,)),
        layers.BatchNormalization(),
        layers.LeakyReLU(),
        layers.Reshape((7, 7, 256)),
        layers.Conv2DTranspose(128, (5,5), strides=(1,1), padding='same', use_bias=False),
        layers.BatchNormalization(),
        layers.LeakyReLU(),
        layers.Conv2DTranspose(64, (5,5), strides=(2,2), padding='same', use_bias=False),
        layers.BatchNormalization(),
        layers.LeakyReLU(),
        layers.Conv2DTranspose(1, (5,5), strides=(2,2), padding='same', use_bias=False, activation='tanh')
    ])
    return model

def make_discriminator_model():
    model = tf.keras.Sequential([
        layers.Conv2D(64, (5,5), strides=(2,2), padding='same', 
                      input_shape=[28, 28, 1]),
        layers.LeakyReLU(),
        layers.Dropout(0.3),
        layers.Conv2D(128, (5,5), strides=(2,2), padding='same'),
        layers.LeakyReLU(),
        layers.Dropout(0.3),
        layers.Flatten(),
        layers.Dense(1)
    ])
    return model

# Carga y preprocesamiento de datos
(train_images, _), (_, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images - 127.5) / 127.5  # Normalización a [-1, 1]

BUFFER_SIZE = 60000
BATCH_SIZE = 256

dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)

# Inicialización de modelos y optimizadores
generator = make_generator_model()
discriminator = make_discriminator_model()

cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)

def discriminator_loss(real_output, fake_output):
    real_loss = cross_entropy(tf.ones_like(real_output), real_output)
    fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)
    total_loss = real_loss + fake_loss
    return total_loss

def generator_loss(fake_output):
    return cross_entropy(tf.ones_like(fake_output), fake_output)

# Optimizadores

generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)

EPOCHS = 50
noise_dim = 100
num_examples_to_generate = 16

seed = tf.random.normal([num_examples_to_generate, noise_dim])

# Función de entrenamiento
@tf.function
def train_step(images):
    noise = tf.random.normal([BATCH_SIZE, noise_dim])

    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
        generated_images = generator(noise, training=True)

        real_output = discriminator(images, training=True)
        fake_output = discriminator(generated_images, training=True)

        gen_loss = generator_loss(fake_output)
        disc_loss = discriminator_loss(real_output, fake_output)

    gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
    gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)

    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
    discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))

# Entrenamiento
for epoch in range(EPOCHS):
    for image_batch in dataset:
        train_step(image_batch)

    print(f'Época {epoch+1} completada')

# Visualización de resultados

def display_images(model, epoch, test_input):
    predictions = model(test_input, training=False)

    fig = plt.figure(figsize=(4,4))

    for i in range(predictions.shape[0]):
        plt.subplot(4, 4, i+1)
        plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='gray')
        plt.axis('off')

    plt.suptitle(f'Imágenes generadas - Época {epoch}')
    plt.show()

display_images(generator, EPOCHS, seed)

Este código define un generador y un discriminador simples, entrenándolos para que la GAN pueda crear imágenes similares a los dígitos manuscritos de MNIST.

Resumen y próximos pasos

Las GANs son potentes herramientas para la generación de contenido en múltiples dominios. Aunque su entrenamiento puede ser desafiante, dominar este concepto abre puertas a aplicaciones innovadoras. Puedes experimentar modificando la arquitectura, probando con otros datasets o explorando variantes como Conditional GANs o CycleGAN.

Autor: Tutor Experto en IA