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.
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.
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.
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
Con la tecnología de
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 =100Con la tecnología de
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.
defload_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)Con la tecnología de
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 optimizerdefget_optimizer():return Adam(lr=0.0002, beta_1=0.5)defget_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
defget_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
Con la tecnología de
Por fin, ¡vamos a juntar el generador y el discriminador!
defget_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
Con la tecnología de
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 imagesdefplot_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 inrange(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)Con la tecnología de
Ya has programado la mayor parte de la red. Solo queda entrenarla y echar un vistazo a las imágenes generadas.
deftrain(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 inxrange(1, epochs+1):print'-'*15,'Epoch %d'% e,'-'*15for _ 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 ==1or e %20==0:
plot_generated_images(e, generator)if __name__ =='__main__':
train(400,128)Con la tecnología de
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
!
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.
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.
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.
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.
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.
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.
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.
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.
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.
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:kerasmatplotlibtensorflowtqdmUsarás
matplotlibpara las gráficas,tensorflowcomo backend de Keras ytqdmpara 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.
Ahora define algunas variables:
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.
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.
Por fin, ¡vamos a juntar el generador y el discriminador!
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.
Ya has programado la mayor parte de la red. Solo queda entrenarla y echar un vistazo a las imágenes generadas.
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.
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.