Ir al contenido principal

Desmitificando las redes generativas antagónicas (GAN)

Aprende qué son las redes generativas antagónicas sin entrar en las matemáticas y programa una GAN sencilla que cree dígitos.
Actualizado 17 sept 2026  · 9 min leer

Explorar con IA

ChatGPTClaudePerplexity

En este tutorial, vas a aprender qué son las redes generativas antagónicas (GAN) sin entrar en los detalles matemáticos. Después, verás cómo programar una GAN sencilla capaz de generar dígitos.

Analogía

La forma más sencilla de entender qué son las GAN es con una analogía:

Imagina una tienda que compra a clientes ciertos tipos de vino para revenderlos después.

analogy

Sin embargo, hay clientes malintencionados que intentan colar vino falso para sacar dinero. En este caso, la persona dueña de la tienda tiene que ser capaz de distinguir entre vinos falsos y auténticos.

analogy

Al principio, es fácil que el falsificador cometa muchos errores al intentar vender vino falso y que a la persona dueña de la tienda le resulte sencillo detectar que no es auténtico. A partir de estos fallos, el falsificador irá probando distintas técnicas para imitar los vinos reales y algunas acabarán funcionando. Una vez que descubre qué técnicas pasan los controles de la tienda, puede seguir mejorando sus falsificaciones en base a ellas.

Al mismo tiempo, a la persona dueña de la tienda probablemente le llegará feedback de otras tiendas o de expertos en vino de que algunos de los vinos que tiene no son originales. Eso significa que tendrá que mejorar su forma de distinguir si un vino es falso o auténtico. El objetivo del falsificador es crear vinos indistinguibles de los reales, y el objetivo de la tienda es identificar con precisión si un vino es auténtico o no.

Esta competición constante es la idea clave detrás de las GAN.

Componentes de una red generativa antagónica

Usando el ejemplo anterior, podemos esbozar la arquitectura de una GAN.

gan

En una GAN hay dos componentes principales: el generador y el discriminador. La persona dueña de la tienda en el ejemplo equivale a la red discriminadora, que suele ser una red neuronal convolucional (ya que las GAN se usan sobre todo en tareas de imagen) que asigna una probabilidad de que una imagen sea real.

El falsificador es la red generadora y, por lo general, también es una red neuronal convolucional (con capas de deconvolución). Esta red toma un vector de ruido y produce una imagen. Al entrenar la red generadora, aprende qué zonas de la imagen debe mejorar o cambiar para que al discriminador le cueste más diferenciar sus imágenes generadas de las reales.

La red generadora va produciendo imágenes cada vez más parecidas a las reales, mientras que la red discriminadora intenta detectar las diferencias entre imágenes reales y falsas. La meta final es tener una generadora que produzca imágenes indistinguibles de las reales.

Una GAN sencilla con Keras

Ahora que ya sabes qué son las GAN y sus componentes principales, vamos a programar una muy simple. Usarás Keras; si no conoces esta librería de Python, te conviene leer este tutorial antes de seguir. Este tutorial se basa en la GAN desarrollada aquí.

Lo primero es instalar estos paquetes con pip:

  • keras
  • matplotlib
  • tensorflow
  • tqdm

Usarás matplotlib para las gráficas, tensorflow como backend de Keras y tqdm para mostrar una barra de progreso en cada época (iteración).

El siguiente paso es crear un script en Python. En él, primero importarás todos los módulos y funciones que vas a usar. Más adelante se explicará cada uno cuando los utilicemos.

import os
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm


from keras.layers import Input
from keras.models import Model, Sequential
from keras.layers.core import Dense, Dropout
from keras.layers.advanced_activations import LeakyReLU
from keras.datasets import mnist
from keras.optimizers import Adam
from keras import initializers

Ahora define algunas variables:

# Let Keras know that we are using tensorflow as our backend engine
os.environ["KERAS_BACKEND"] = "tensorflow"

# To make sure that we can reproduce the experiment and get the same results
np.random.seed(10)

# The dimension of our random noise vector.
random_dim = 100

Antes de construir el discriminador y el generador, primero debes recopilar y preprocesar los datos. Usarás el conocido conjunto de datos MNIST, que contiene imágenes de dígitos del 0 al 9.

mnist dataset

def load_minst_data():
    # load the data
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    # normalize our inputs to be in the range[-1, 1]
    x_train = (x_train.astype(np.float32) - 127.5)/127.5
    # convert x_train with a shape of (60000, 28, 28) to (60000, 784) so we have
    # 784 columns per row
    x_train = x_train.reshape(60000, 784)
    return (x_train, y_train, x_test, y_test)

Nota: mnist.load_data() forma parte de Keras y te permite importar fácilmente el conjunto de datos MNIST a tu espacio de trabajo.

Ahora puedes crear las redes generadora y discriminadora. Usarás el optimizador Adam para ambas. Tanto para el generador como para el discriminador, crearás una red neuronal con tres capas ocultas y función de activación Leaky ReLU. También deberías añadir capas de dropout al discriminador para mejorar su robustez con imágenes no vistas.

# You will use the Adam optimizer
def get_optimizer():
    return Adam(lr=0.0002, beta_1=0.5)

def get_generator(optimizer):
    generator = Sequential()
    generator.add(Dense(256, input_dim=random_dim, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(512))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(1024))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(784, activation='tanh'))
    generator.compile(loss='binary_crossentropy', optimizer=optimizer)
    return generator

def get_discriminator(optimizer):
    discriminator = Sequential()
    discriminator.add(Dense(1024, input_dim=784, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(512))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(256))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(1, activation='sigmoid'))
    discriminator.compile(loss='binary_crossentropy', optimizer=optimizer)
    return discriminator

Por fin, ¡vamos a juntar el generador y el discriminador!

def get_gan_network(discriminator, random_dim, generator, optimizer):
    # We initially set trainable to False since we only want to train either the
    # generator or discriminator at a time
    discriminator.trainable = False
    # gan input (noise) will be 100-dimensional vectors
    gan_input = Input(shape=(random_dim,))
    # the output of the generator (an image)
    x = generator(gan_input)
    # get the output of the discriminator (probability if the image is real or not)
    gan_output = discriminator(x)
    gan = Model(inputs=gan_input, outputs=gan_output)
    gan.compile(loss='binary_crossentropy', optimizer=optimizer)
    return gan

Para completar, puedes crear una función que guarde las imágenes generadas cada 20 épocas. Como no es el centro de esta lección, no necesitas entenderla en detalle.

# Create a wall of generated MNIST images
def plot_generated_images(epoch, generator, examples=100, dim=(10, 10), figsize=(10, 10)):
    noise = np.random.normal(0, 1, size=[examples, random_dim])
    generated_images = generator.predict(noise)
    generated_images = generated_images.reshape(examples, 28, 28)

    plt.figure(figsize=figsize)
    for i in range(generated_images.shape[0]):
        plt.subplot(dim[0], dim[1], i+1)
        plt.imshow(generated_images[i], interpolation='nearest', cmap='gray_r')
        plt.axis('off')
    plt.tight_layout()
    plt.savefig('gan_generated_image_epoch_%d.png' % epoch)

Ya has programado la mayor parte de la red. Solo queda entrenarla y echar un vistazo a las imágenes generadas.

def train(epochs=1, batch_size=128):
    # Get the training and testing data
    x_train, y_train, x_test, y_test = load_minst_data()
    # Split the training data into batches of size 128
    batch_count = x_train.shape[0] / batch_size

    # Build our GAN netowrk
    adam = get_optimizer()
    generator = get_generator(adam)
    discriminator = get_discriminator(adam)
    gan = get_gan_network(discriminator, random_dim, generator, adam)

    for e in xrange(1, epochs+1):
        print '-'*15, 'Epoch %d' % e, '-'*15
        for _ in tqdm(xrange(batch_count)):
            # Get a random set of input noise and images
            noise = np.random.normal(0, 1, size=[batch_size, random_dim])
            image_batch = x_train[np.random.randint(0, x_train.shape[0], size=batch_size)]

            # Generate fake MNIST images
            generated_images = generator.predict(noise)
            X = np.concatenate([image_batch, generated_images])

            # Labels for generated and real data
            y_dis = np.zeros(2*batch_size)
            # One-sided label smoothing
            y_dis[:batch_size] = 0.9

            # Train discriminator
            discriminator.trainable = True
            discriminator.train_on_batch(X, y_dis)

            # Train generator
            noise = np.random.normal(0, 1, size=[batch_size, random_dim])
            y_gen = np.ones(batch_size)
            discriminator.trainable = False
            gan.train_on_batch(noise, y_gen)

        if e == 1 or e % 20 == 0:
            plot_generated_images(e, generator)

if __name__ == '__main__':
    train(400, 128)

Tras entrenar durante 400 épocas, puedes ver las imágenes generadas. Si miras las imágenes producidas después de la primera época, verás que no tienen estructura. Tras 40 épocas, los dígitos empiezan a tomar forma y, finalmente, después de 400 épocas se aprecian dígitos claros, aunque un par siguen siendo irreconocibles.

Resultados tras 1 época Resultados tras 40 épocas Resultados tras 400 épocas
!images1 images2 images3

Este código tarda aproximadamente 2 minutos por época en una CPU, y esa es la razón principal por la que lo hemos elegido. Puedes experimentar con más épocas y añadiendo más (y diferentes) capas tanto al generador como al discriminador. Eso sí, si usas arquitecturas más complejas y profundas, el tiempo de ejecución aumentará si solo cuentas con CPU. Aun así, no dejes de probar.

Conclusión

¡Enhorabuena! Has llegado al final del tutorial, donde has aprendido los fundamentos de las redes generativas antagónicas (GAN) de forma intuitiva. Además, has implementado tu primer modelo con la ayuda de la librería Keras. Si quieres saber más sobre deep learning con Python, échale un vistazo al curso Deep Learning in Python de DataCamp.

Temas
Aprendizaje profundo
Inteligencia Artificial
Aprendizaje automático

Aprende más sobre Python y deep learning

Curso

Introducción al Deep Learning en Python

4 h
264.6K
Aprende los fundamentos de las redes neuronales y cómo construir modelos de aprendizaje profundo con Keras 2.0 en Python.
Ver detallesRight Arrow
Iniciar Curso
Ver másRight Arrow
Relacionado

blog

¿Qué es un modelo generativo?

Los modelos generativos utilizan el machine learning para descubrir patrones en los datos y generar datos nuevos. Conoce su importancia y sus aplicaciones en la IA.
Abid Ali Awan's photo

Abid Ali Awan

11 min

An AI juggles tasks

blog

Cinco proyectos que puedes crear con modelos de IA generativa (con ejemplos)

Aprende a utilizar modelos de IA generativa para crear un editor de imágenes, un chatbot similar a ChatGPT con pocos recursos y una aplicación clasificadora de aprobación de préstamos y a automatizar interacciones PDF y un asistente de voz con GPT.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

Modelos Generativos vs Discriminativos: Diferencias y casos de uso

Este artículo explica las principales diferencias entre los modelos generativos y los discriminativos, cubriendo sus principios, casos de uso y ejemplos prácticos para ayudarte a elegir el enfoque adecuado para tus tareas de aprendizaje automático.
Arun Nanda's photo

Arun Nanda

15 min

GNN

Tutorial

Introducción completa a las redes neuronales gráficas (GNN)

Aprenda todo sobre las redes neuronales gráficas, incluyendo qué son las GNN, los diferentes tipos de redes neuronales gráficas y para qué se utilizan. Además, aprenda a crear una red neuronal gráfica con Pytorch.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Tutorial

Introducción a las redes neuronales profundas

Comprender las redes neuronales profundas y su importancia en el mundo moderno del aprendizaje profundo de la inteligencia artificial
Bharath K's photo

Bharath K

13 min

Tutorial

Introducción a las redes neuronales convolucionales (CNN)

Una guía completa para entender las CNN, su impacto en el análisis de imágenes y algunas estrategias clave para combatir el sobreajuste en aplicaciones robustas de CNN frente al aprendizaje profundo.
Zoumana Keita 's photo

Zoumana Keita

14 min

Ver MásVer Más